summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfoxsen <foxsen@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-07-11 05:58:33 +0000
committerfoxsen <foxsen@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-07-11 05:58:33 +0000
commit0321f8d9bde18cc19bf642102f287ab6eade382f (patch)
treead6224bc825907ba6b8a03d849e4396298fb53e3
parenta18fe56f5e2c634b35936e044f1e95573699e77d (diff)
downloadfpc-foxsen.tar.gz
merge to trunk 21856foxsen
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/foxsen@21858 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--mips/compiler/Makefile59
-rw-r--r--mips/compiler/Makefile.fpc53
-rw-r--r--mips/compiler/aasmbase.pas14
-rw-r--r--mips/compiler/aasmtai.pas42
-rw-r--r--mips/compiler/aggas.pas30
-rw-r--r--mips/compiler/alpha/aasmcpu.pas13
-rw-r--r--mips/compiler/aopt.pas3
-rw-r--r--mips/compiler/aoptbase.pas6
-rw-r--r--mips/compiler/aoptobj.pas2
-rw-r--r--mips/compiler/arm/aasmcpu.pas8
-rw-r--r--mips/compiler/arm/agarmgas.pas18
-rw-r--r--mips/compiler/arm/aoptcpu.pas117
-rw-r--r--mips/compiler/arm/cgcpu.pas213
-rw-r--r--mips/compiler/arm/cpubase.pas35
-rw-r--r--mips/compiler/arm/cpupara.pas54
-rw-r--r--mips/compiler/arm/cpupi.pas2
-rw-r--r--mips/compiler/arm/narminl.pas20
-rw-r--r--mips/compiler/arm/narmmat.pas137
-rw-r--r--mips/compiler/arm/raarmgas.pas2
-rw-r--r--mips/compiler/assemble.pas8
-rw-r--r--mips/compiler/avr/cgcpu.pas14
-rw-r--r--mips/compiler/avr/cpubase.pas4
-rw-r--r--mips/compiler/avr/cpupara.pas54
-rw-r--r--mips/compiler/avr/raavrgas.pas2
-rw-r--r--mips/compiler/cgbase.pas5
-rw-r--r--mips/compiler/cgobj.pas283
-rw-r--r--mips/compiler/cgutils.pas10
-rw-r--r--mips/compiler/cutils.pas24
-rw-r--r--mips/compiler/dbgstabs.pas58
-rw-r--r--mips/compiler/defcmp.pas15
-rw-r--r--mips/compiler/fpcdefs.inc26
-rw-r--r--mips/compiler/fppu.pas129
-rw-r--r--mips/compiler/globals.pas7
-rw-r--r--mips/compiler/globtype.pas14
-rw-r--r--mips/compiler/hlcg2ll.pas49
-rw-r--r--mips/compiler/hlcgobj.pas338
-rw-r--r--mips/compiler/htypechk.pas4
-rw-r--r--mips/compiler/i386/cpupara.pas83
-rw-r--r--mips/compiler/jvm/cpubase.pas2
-rw-r--r--mips/compiler/jvm/cpupara.pas6
-rw-r--r--mips/compiler/jvm/hlcgcpu.pas7
-rw-r--r--mips/compiler/jvm/njvmld.pas7
-rw-r--r--mips/compiler/link.pas62
-rw-r--r--mips/compiler/m68k/cpubase.pas2
-rw-r--r--mips/compiler/m68k/cpupara.pas50
-rw-r--r--mips/compiler/m68k/ra68kmot.pas2
-rw-r--r--mips/compiler/mips/aasmcpu.pas147
-rw-r--r--mips/compiler/mips/cgcpu.pas330
-rw-r--r--mips/compiler/mips/cpubase.pas36
-rw-r--r--mips/compiler/mips/cpugas.pas141
-rw-r--r--mips/compiler/mips/cpunode.pas3
-rw-r--r--mips/compiler/mips/cpupara.pas352
-rw-r--r--mips/compiler/mips/cpupi.pas67
-rw-r--r--mips/compiler/mips/hlcgcpu.pas69
-rw-r--r--mips/compiler/mips/mipsreg.dat76
-rw-r--r--mips/compiler/mips/ncpucall.pas14
-rw-r--r--mips/compiler/mips/ncpuld.pas72
-rw-r--r--mips/compiler/mips/opcode.inc3
-rw-r--r--mips/compiler/mips/rmipssri.inc20
-rw-r--r--mips/compiler/mips/rmipsstd.inc76
-rw-r--r--mips/compiler/mips/strinst.inc3
-rw-r--r--mips/compiler/msg/errore.msg9
-rw-r--r--mips/compiler/msgidx.inc5
-rw-r--r--mips/compiler/msgtxt.inc820
-rw-r--r--mips/compiler/nbas.pas2
-rw-r--r--mips/compiler/ncgcal.pas18
-rw-r--r--mips/compiler/ncgflw.pas30
-rw-r--r--mips/compiler/ncginl.pas98
-rw-r--r--mips/compiler/ncgld.pas2
-rw-r--r--mips/compiler/ncgmat.pas2
-rw-r--r--mips/compiler/ncgmem.pas12
-rw-r--r--mips/compiler/ncgopt.pas4
-rw-r--r--mips/compiler/ncgutil.pas24
-rw-r--r--mips/compiler/ncnv.pas36
-rw-r--r--mips/compiler/nobj.pas7
-rw-r--r--mips/compiler/ogbase.pas260
-rw-r--r--mips/compiler/ogcoff.pas203
-rw-r--r--mips/compiler/ogelf.pas589
-rw-r--r--mips/compiler/options.pas10
-rw-r--r--mips/compiler/paramgr.pas54
-rw-r--r--mips/compiler/pdecobj.pas14
-rw-r--r--mips/compiler/pdecsub.pas72
-rw-r--r--mips/compiler/pexpr.pas5
-rw-r--r--mips/compiler/pgenutil.pas192
-rw-r--r--mips/compiler/powerpc/cpubase.pas2
-rw-r--r--mips/compiler/powerpc/cpupara.pas51
-rw-r--r--mips/compiler/powerpc/nppcmat.pas8
-rw-r--r--mips/compiler/powerpc64/cpubase.pas2
-rw-r--r--mips/compiler/powerpc64/cpupara.pas53
-rw-r--r--mips/compiler/pparautl.pas7
-rw-r--r--mips/compiler/ppcgen/cgppc.pas2
-rw-r--r--mips/compiler/ppu.pas2
-rw-r--r--mips/compiler/pstatmnt.pas2
-rw-r--r--mips/compiler/psub.pas40
-rw-r--r--mips/compiler/psystem.pas3
-rw-r--r--mips/compiler/ptype.pas109
-rw-r--r--mips/compiler/rautils.pas1
-rw-r--r--mips/compiler/rgobj.pas21
-rw-r--r--mips/compiler/scanner.pas174
-rw-r--r--mips/compiler/sparc/cgcpu.pas8
-rw-r--r--mips/compiler/sparc/cpubase.pas4
-rw-r--r--mips/compiler/sparc/cpupara.pas65
-rw-r--r--mips/compiler/symdef.pas4
-rw-r--r--mips/compiler/symtable.pas44
-rw-r--r--mips/compiler/systems/i_linux.pas4
-rw-r--r--mips/compiler/systems/t_go32v2.pas2
-rw-r--r--mips/compiler/systems/t_linux.pas291
-rw-r--r--mips/compiler/systems/t_win.pas25
-rw-r--r--mips/compiler/utils/Makefile19
-rw-r--r--mips/compiler/utils/fpc.pp13
-rw-r--r--mips/compiler/verbose.pas30
-rw-r--r--mips/compiler/version.pas2
-rw-r--r--mips/compiler/x86/aasmcpu.pas6
-rw-r--r--mips/compiler/x86/agx86int.pas4
-rw-r--r--mips/compiler/x86/agx86nsm.pas4
-rw-r--r--mips/compiler/x86/cgx86.pas2
-rw-r--r--mips/compiler/x86/cpubase.pas3
-rw-r--r--mips/compiler/x86/nx86inl.pas3
-rw-r--r--mips/compiler/x86_64/cgcpu.pas4
-rw-r--r--mips/compiler/x86_64/cpupara.pas78
-rw-r--r--mips/ide/fp.pas3
-rw-r--r--mips/ide/fpredir.pas11
-rw-r--r--mips/ide/fputils.pas11
-rw-r--r--mips/packages/fcl-db/src/base/bufdataset.pas102
-rw-r--r--mips/packages/fcl-db/src/base/dataset.inc60
-rw-r--r--mips/packages/fcl-db/src/base/dbconst.pas2
-rw-r--r--mips/packages/fcl-db/src/base/dsparams.inc32
-rw-r--r--mips/packages/fcl-db/src/base/xmldatapacketreader.pp112
-rw-r--r--mips/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc33
-rw-r--r--mips/packages/fcl-db/src/sqldb/postgres/pqconnection.pp182
-rw-r--r--mips/packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp1
-rw-r--r--mips/packages/fcl-db/src/sqldb/sqldb.pp160
-rw-r--r--mips/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp1
-rw-r--r--mips/packages/fcl-db/tests/bufdatasettoolsunit.pas19
-rw-r--r--mips/packages/fcl-db/tests/dbtestframework.pas9
-rw-r--r--mips/packages/fcl-db/tests/testbasics.pas126
-rw-r--r--mips/packages/fcl-db/tests/testbufdatasetstreams.pas121
-rw-r--r--mips/packages/fcl-db/tests/testdbbasics.pas65
-rw-r--r--mips/packages/fcl-db/tests/testfieldtypes.pas76
-rw-r--r--mips/packages/fcl-db/tests/testspecifictbufdataset.pas125
-rw-r--r--mips/packages/fcl-db/tests/toolsunit.pas2
-rw-r--r--mips/packages/fcl-fpcunit/src/fpcunit.pp12
-rw-r--r--mips/packages/fcl-image/examples/Makefile181
-rw-r--r--mips/packages/fcl-image/examples/Makefile.fpc2
-rw-r--r--mips/packages/fcl-image/examples/drawing.pp22
-rw-r--r--mips/packages/fcl-image/examples/interpoldemo.pp39
-rw-r--r--mips/packages/fcl-image/fpmake.pp6
-rw-r--r--mips/packages/fcl-image/src/fpcompactimg.inc597
-rw-r--r--mips/packages/fcl-image/src/fpimage.pp197
-rw-r--r--mips/packages/fcl-image/src/fpimggauss.pp701
-rw-r--r--mips/packages/fcl-image/src/fpinterpolation.inc4
-rw-r--r--mips/packages/fcl-image/src/fpwritepng.pp1
-rw-r--r--mips/packages/fcl-json/src/fpjson.pp15
-rw-r--r--mips/packages/fcl-json/src/fpjsonrtti.pp9
-rw-r--r--mips/packages/fcl-json/src/jsonparser.pp32
-rw-r--r--mips/packages/fcl-json/src/jsonscanner.pp20
-rw-r--r--mips/packages/fcl-passrc/src/pastree.pp23
-rw-r--r--mips/packages/fcl-passrc/src/pparser.pp197
-rw-r--r--mips/packages/fcl-passrc/src/pscanner.pp2
-rw-r--r--mips/packages/fcl-process/src/dummy/pipes.inc2
-rw-r--r--mips/packages/fcl-process/src/os2/pipes.inc4
-rw-r--r--mips/packages/fcl-process/src/pipes.pp2
-rw-r--r--mips/packages/fcl-process/src/process.pp5
-rw-r--r--mips/packages/fcl-process/src/unix/pipes.inc2
-rw-r--r--mips/packages/fcl-process/src/unix/process.inc2
-rw-r--r--mips/packages/fcl-process/src/win/pipes.inc4
-rw-r--r--mips/packages/fcl-process/src/win/process.inc10
-rw-r--r--mips/packages/fcl-process/src/wince/process.inc10
-rw-r--r--mips/packages/fcl-web/src/base/httpdefs.pp106
-rw-r--r--mips/packages/fcl-web/src/base/iniwebsession.pp26
-rw-r--r--mips/packages/fpindexer/src/dbindexer.pp1
-rw-r--r--mips/packages/libpng/src/png.pp1
-rw-r--r--mips/packages/winunits-base/src/eventsink.pp21
-rw-r--r--mips/rtl/arm/arm.inc117
-rw-r--r--mips/rtl/arm/divide.inc4
-rw-r--r--mips/rtl/arm/strings.inc47
-rw-r--r--mips/rtl/avr/avr.inc4
-rw-r--r--mips/rtl/i386/i386.inc10
-rw-r--r--mips/rtl/inc/compproc.inc3
-rw-r--r--mips/rtl/inc/except.inc9
-rw-r--r--mips/rtl/inc/generic.inc2
-rw-r--r--mips/rtl/inc/heaptrc.pp60
-rw-r--r--mips/rtl/inc/system.inc70
-rw-r--r--mips/rtl/inc/systemh.inc15
-rw-r--r--mips/rtl/inc/variant.inc2
-rw-r--r--mips/rtl/java/jastringh.inc1
-rw-r--r--mips/rtl/java/jastrings.inc7
-rw-r--r--mips/rtl/java/java_sysh.inc25
-rw-r--r--mips/rtl/java/jcompproc.inc2
-rw-r--r--mips/rtl/java/jsystemh.inc10
-rw-r--r--mips/rtl/jvm/jvm.inc6
-rw-r--r--mips/rtl/linux/Makefile13
-rw-r--r--mips/rtl/linux/Makefile.fpc14
-rw-r--r--mips/rtl/linux/errno-mips.inc147
-rw-r--r--mips/rtl/linux/errno.inc5
-rw-r--r--mips/rtl/linux/mips/cprt0.as149
-rw-r--r--mips/rtl/linux/mips/dllprt0.as1
-rw-r--r--mips/rtl/linux/mips/gprt0.as1
-rw-r--r--mips/rtl/linux/mips/prt0.as8
-rw-r--r--mips/rtl/linux/mips/sighnd.inc35
-rw-r--r--mips/rtl/linux/mips/sighndh.inc80
-rw-r--r--mips/rtl/linux/mips/syscall.inc16
-rw-r--r--mips/rtl/linux/ossysc.inc18
-rw-r--r--mips/rtl/linux/ostypes.inc18
-rw-r--r--mips/rtl/linux/ptypes.inc133
-rw-r--r--mips/rtl/linux/signal.inc59
-rw-r--r--mips/rtl/linux/sparc/sighnd.inc2
-rw-r--r--mips/rtl/linux/unxsockh.inc10
-rw-r--r--mips/rtl/linux/x86_64/dllprt0.as4
-rw-r--r--mips/rtl/m68k/m68k.inc4
-rw-r--r--mips/rtl/mips/mathu.inc123
-rw-r--r--mips/rtl/mips/mips.inc136
-rw-r--r--mips/rtl/objpas/fgl.pp2
-rw-r--r--mips/rtl/objpas/strutils.pp21
-rw-r--r--mips/rtl/openbsd/errno.inc20
-rw-r--r--mips/rtl/powerpc/powerpc.inc4
-rw-r--r--mips/rtl/powerpc64/powerpc64.inc4
-rw-r--r--mips/rtl/sparc/sparc.inc6
-rw-r--r--mips/rtl/unix/ipc.pp12
-rwxr-xr-xmips/rtl/unix/scripts/check_consts.sh4
-rwxr-xr-xmips/rtl/unix/scripts/check_errno.sh110
-rw-r--r--mips/rtl/win/crt.pp9
-rw-r--r--mips/rtl/x86_64/x86_64.inc11
-rw-r--r--mips/tests/Makefile1
-rw-r--r--mips/tests/Makefile.fpc5
-rw-r--r--mips/tests/tbs/tb0193.pp16
-rw-r--r--mips/tests/tbs/tb0524.pp64
-rw-r--r--mips/tests/tbs/tb0528.pp2
-rw-r--r--mips/tests/test/jvm/tenum2.pp34
-rw-r--r--mips/tests/test/jvm/testall.bat11
-rwxr-xr-xmips/tests/test/jvm/testall.sh6
-rw-r--r--mips/tests/test/jvm/tsetansistr.pp31
-rw-r--r--mips/tests/test/opt/tretopt.pp4
-rw-r--r--mips/tests/test/packages/bzip2/tbzip2streamtest.pp85
-rw-r--r--mips/tests/test/tasmread.pp2
-rw-r--r--mips/tests/test/tcg1.pp133
-rw-r--r--mips/tests/test/testsse2.pp2
-rw-r--r--mips/tests/test/tgeneric76.pp45
-rw-r--r--mips/tests/test/tgeneric77.pp48
-rw-r--r--mips/tests/test/tgeneric78.pp27
-rw-r--r--mips/tests/test/tgeneric79.pp27
-rw-r--r--mips/tests/test/tgeneric80.pp18
-rw-r--r--mips/tests/test/tgeneric81.pp18
-rw-r--r--mips/tests/test/tgeneric82.pp18
-rw-r--r--mips/tests/test/tgeneric83.pp16
-rw-r--r--mips/tests/test/tgeneric84.pp14
-rw-r--r--mips/tests/test/tgeneric85.pp16
-rw-r--r--mips/tests/test/tgeneric86.pp17
-rw-r--r--mips/tests/test/tgeneric87.pp18
-rw-r--r--mips/tests/test/tgeneric88.pp17
-rw-r--r--mips/tests/test/tgeneric89.pp17
-rw-r--r--mips/tests/test/tgeneric90.pp26
-rw-r--r--mips/tests/test/tint642.pp4
-rw-r--r--mips/tests/test/trhlp44.pp31
-rw-r--r--mips/tests/webtbf/tw22219.pp16
-rw-r--r--mips/tests/webtbs/tw20947.pp21
-rw-r--r--mips/tests/webtbs/tw20998.pp23
-rw-r--r--mips/tests/webtbs/tw21064a.pp26
-rw-r--r--mips/tests/webtbs/tw21064b.pp28
-rw-r--r--mips/tests/webtbs/tw21350a.pp45
-rw-r--r--mips/tests/webtbs/tw21350b.pp47
-rw-r--r--mips/tests/webtbs/tw21457.pp24
-rw-r--r--mips/tests/webtbs/tw21921.pp28
-rw-r--r--mips/tests/webtbs/tw22154.pp18
-rw-r--r--mips/tests/webtbs/tw22320.pp73
-rw-r--r--mips/tests/webtbs/tw22326.pp9
-rw-r--r--mips/tests/webtbs/tw22329.pp32
-rw-r--r--mips/tests/webtbs/tw22331.pp139
-rw-r--r--mips/tests/webtbs/tw22344.pp24
269 files changed, 9569 insertions, 3901 deletions
diff --git a/mips/compiler/Makefile b/mips/compiler/Makefile
index 1beac0d0b4..0292a943f3 100644
--- a/mips/compiler/Makefile
+++ b/mips/compiler/Makefile
@@ -1,5 +1,5 @@
#
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/04/25]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/06/13]
#
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 powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux jvm-java jvm-android
@@ -362,6 +362,32 @@ endif
ifndef RTLOPT
RTLOPT:=$(OPT)
endif
+ifdef CYCLELEVEL
+ifeq ($(CYCLELEVEL),1)
+LOCALOOPT+=$(OPTLEVEL1)
+RTLOPT+=$(OPTLEVEL1)
+LOCALOPT+=$(LOCALOPTLEVEL1)
+RTLOPT+=$(RTLOPTLEVEL1)
+endif
+ifeq ($(CYCLELEVEL),2)
+LOCALOOPT+=$(OPTLEVEL2)
+RTLOPT+=$(OPTLEVEL2)
+LOCALOPT+=$(LOCALOPTLEVEL2)
+RTLOPT+=$(RTLOPTLEVEL2)
+endif
+ifeq ($(CYCLELEVEL),3)
+LOCALOOPT+=$(OPTLEVEL3)
+RTLOPT+=$(OPTLEVEL3)
+LOCALOPT+=$(LOCALOPTLEVEL3)
+RTLOPT+=$(RTLOPTLEVEL3)
+endif
+ifeq ($(CYCLELEVEL),4)
+LOCALOOPT+=$(OPTLEVEL4)
+RTLOPT+=$(OPTLEVEL4)
+LOCALOPT+=$(LOCALOPTLEVEL4)
+RTLOPT+=$(RTLOPTLEVEL4)
+endif
+endif
override OPT=
MSGFILES=$(wildcard msg/error*.msg)
ifeq ($(CPC_TARGET),i386)
@@ -2702,17 +2728,12 @@ 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
@@ -3674,20 +3695,20 @@ next :
$(MAKE) echotime
endif
$(TEMPNAME1) :
- $(MAKE) 'OLDFPC=' next
+ $(MAKE) 'OLDFPC=' next CYCLELEVEL=1
-$(DEL) $(TEMPNAME1)
$(MOVE) $(EXENAME) $(TEMPNAME1)
$(TEMPNAME2) : $(TEMPNAME1)
- $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next CYCLELEVEL=2
-$(DEL) $(TEMPNAME2)
$(MOVE) $(EXENAME) $(TEMPNAME2)
$(TEMPNAME3) : $(TEMPNAME2)
- $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next CYCLELEVEL=3
-$(DEL) $(TEMPNAME3)
$(MOVE) $(EXENAME) $(TEMPNAME3)
cycle:
$(MAKE) tempclean $(TEMPNAME3)
- $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next CYCLELEVEL=4
$(DIFF) $(TEMPNAME3) $(EXENAME)
$(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAME)'
$(MAKE) wpocycle
@@ -3695,14 +3716,14 @@ cycle:
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) OS_TARGET=$(OS_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=1
$(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
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
ifndef CROSSINSTALL
$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
ifneq ($(OS_TARGET),embedded)
ifneq ($(OS_TARGET),gba)
- $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler CYCLELEVEL=3
endif
endif
endif
@@ -3711,27 +3732,31 @@ 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) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=1
$(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
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
ifndef CROSSINSTALL
$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(RTLOPT) $(CROSSOPT)' rtlclean rtl
ifndef NoNativeBinaries
- $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(LOCALOPT) $(CROSSOPT)' cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(LOCALOPT) $(CROSSOPT)' cycleclean compiler CYCLELEVEL=3
endif
endif
endif
cycledep:
$(MAKE) cycle USEDEPEND=1
extcycle:
- $(MAKE) cycle OPT='-n -OG2p3 -glttt -CRriot -dEXTDEBUG'
+ $(MAKE) cycle OPT="$(OPT) -n -OG2p3 -glttt -CRriot -dEXTDEBUG"
cvstest:
$(MAKE) cycle 'LOCALOPT=-n -Se' 'RTLOPT=-n -Se'
full: fullcycle
fullcycle:
$(MAKE) cycle
$(MAKE) ppuclean
+ifneq ($(CPU_SOURCE),x86_64)
$(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+else
+ $(MAKE) $(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS))) 'FPC=$(BASEDIR)/$(EXENAME)'
+endif
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
diff --git a/mips/compiler/Makefile.fpc b/mips/compiler/Makefile.fpc
index 7b92695a05..8f24b83262 100644
--- a/mips/compiler/Makefile.fpc
+++ b/mips/compiler/Makefile.fpc
@@ -123,6 +123,33 @@ ifndef RTLOPT
RTLOPT:=$(OPT)
endif
+ifdef CYCLELEVEL
+ifeq ($(CYCLELEVEL),1)
+LOCALOOPT+=$(OPTLEVEL1)
+RTLOPT+=$(OPTLEVEL1)
+LOCALOPT+=$(LOCALOPTLEVEL1)
+RTLOPT+=$(RTLOPTLEVEL1)
+endif
+ifeq ($(CYCLELEVEL),2)
+LOCALOOPT+=$(OPTLEVEL2)
+RTLOPT+=$(OPTLEVEL2)
+LOCALOPT+=$(LOCALOPTLEVEL2)
+RTLOPT+=$(RTLOPTLEVEL2)
+endif
+ifeq ($(CYCLELEVEL),3)
+LOCALOOPT+=$(OPTLEVEL3)
+RTLOPT+=$(OPTLEVEL3)
+LOCALOPT+=$(LOCALOPTLEVEL3)
+RTLOPT+=$(RTLOPTLEVEL3)
+endif
+ifeq ($(CYCLELEVEL),4)
+LOCALOOPT+=$(OPTLEVEL4)
+RTLOPT+=$(OPTLEVEL4)
+LOCALOPT+=$(LOCALOPTLEVEL4)
+RTLOPT+=$(RTLOPTLEVEL4)
+endif
+endif
+
# Make OPT empty. It is copied to LOCALOPT and RTLOPT
override OPT=
@@ -582,23 +609,23 @@ next :
endif
$(TEMPNAME1) :
- $(MAKE) 'OLDFPC=' next
+ $(MAKE) 'OLDFPC=' next CYCLELEVEL=1
-$(DEL) $(TEMPNAME1)
$(MOVE) $(EXENAME) $(TEMPNAME1)
$(TEMPNAME2) : $(TEMPNAME1)
- $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next CYCLELEVEL=2
-$(DEL) $(TEMPNAME2)
$(MOVE) $(EXENAME) $(TEMPNAME2)
$(TEMPNAME3) : $(TEMPNAME2)
- $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next CYCLELEVEL=3
-$(DEL) $(TEMPNAME3)
$(MOVE) $(EXENAME) $(TEMPNAME3)
cycle:
$(MAKE) tempclean $(TEMPNAME3)
- $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next CYCLELEVEL=4
$(DIFF) $(TEMPNAME3) $(EXENAME)
$(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAME)'
$(MAKE) wpocycle
@@ -613,10 +640,10 @@ else
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
+ $(MAKE) OS_TARGET=$(OS_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=1
# 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
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
# ppc<ARCH> (target native)
ifndef CROSSINSTALL
$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
@@ -624,7 +651,7 @@ ifndef CROSSINSTALL
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
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler CYCLELEVEL=3
endif
endif
endif
@@ -646,16 +673,16 @@ 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
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=1
# 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
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler CYCLELEVEL=2
# ppc<ARCH> (target native)
ifndef CROSSINSTALL
$(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(RTLOPT) $(CROSSOPT)' rtlclean rtl
# building a native compiler for JVM and embedded targets is not possible
ifndef NoNativeBinaries
- $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(LOCALOPT) $(CROSSOPT)' cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(LOCALOPT) $(CROSSOPT)' cycleclean compiler CYCLELEVEL=3
endif
endif
@@ -665,7 +692,7 @@ cycledep:
$(MAKE) cycle USEDEPEND=1
extcycle:
- $(MAKE) cycle OPT='-n -OG2p3 -glttt -CRriot -dEXTDEBUG'
+ $(MAKE) cycle OPT="$(OPT) -n -OG2p3 -glttt -CRriot -dEXTDEBUG"
cvstest:
$(MAKE) cycle 'LOCALOPT=-n -Se' 'RTLOPT=-n -Se'
@@ -685,7 +712,11 @@ full: fullcycle
fullcycle:
$(MAKE) cycle
$(MAKE) ppuclean
+ifneq ($(CPU_SOURCE),x86_64)
$(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+else
+ $(MAKE) $(filter-out i386,$(filter-out $(PPC_TARGET),$(CYCLETARGETS))) 'FPC=$(BASEDIR)/$(EXENAME)'
+endif
#####################################################################
# Docs
diff --git a/mips/compiler/aasmbase.pas b/mips/compiler/aasmbase.pas
index 04eb2d1260..9fe07535fb 100644
--- a/mips/compiler/aasmbase.pas
+++ b/mips/compiler/aasmbase.pas
@@ -191,6 +191,15 @@ interface
function ReplaceForbiddenAsmSymbolChars(const s: string): string;
+ { dummy default noop callback }
+ procedure default_global_used;
+ type
+ TGlobalUsedProcedure = procedure;
+ { Procedure variable to allow for special handling of
+ the occurence of use of a global variable,
+ used by PIC code generation to request GOT loading }
+ const
+ global_used : TGlobalUsedProcedure = @default_global_used;
implementation
@@ -420,6 +429,7 @@ implementation
is_set:=false;
{ write it always }
increfs;
+ global_used;
end;
@@ -447,4 +457,8 @@ implementation
increfs;
end;
+ procedure default_global_used;
+ begin
+ end;
+
end.
diff --git a/mips/compiler/aasmtai.pas b/mips/compiler/aasmtai.pas
index 2b8e9ce15d..fee6ce2766 100644
--- a/mips/compiler/aasmtai.pas
+++ b/mips/compiler/aasmtai.pas
@@ -68,10 +68,13 @@ interface
ait_stab,
ait_force_line,
ait_function_name,
+ { Used for .ent .end pair used for .dpr section in MIPS
+ and probably also for Alpha }
+ ait_ent,
+ ait_ent_end,
{$ifdef alpha}
{ the follow is for the DEC Alpha }
ait_frame,
- ait_ent,
{$endif alpha}
{$ifdef ia64}
ait_bundle,
@@ -163,10 +166,11 @@ interface
'stab',
'force_line',
'function_name',
+ 'ent',
+ 'ent_end',
{$ifdef alpha}
{ the follow is for the DEC Alpha }
'frame',
- 'ent',
{$endif alpha}
{$ifdef ia64}
'bundle',
@@ -261,7 +265,8 @@ interface
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_regalloc, ait_tempalloc, ait_symbol_end
+ ,ait_ent, ait_ent_end, ait_directive
,ait_varloc,ait_seh_directive
,ait_jvar, ait_jcatch];
@@ -272,6 +277,7 @@ interface
ait_stab,ait_function_name,
ait_cutobject,ait_marker,ait_varloc,ait_align,ait_section,ait_comment,
ait_const,ait_directive,
+ ait_ent, ait_ent_end,
{$ifdef arm}
ait_thumb_func,
{$endif arm}
@@ -420,6 +426,16 @@ interface
procedure derefimpl;override;
end;
+ tai_ent = class(tai)
+ Name : string;
+ Constructor Create (const ProcName : String);
+ end;
+
+ tai_ent_end = class(tai)
+ Name : string;
+ Constructor Create (const ProcName : String);
+ end;
+
tai_directive = class(tailineinfo)
name : ansistring;
directive : TAsmDirective;
@@ -1246,6 +1262,26 @@ implementation
ppufile.putbyte(byte(directive));
end;
+{****************************************************************************
+ TAI_ENT / TAI_ENT_END
+ ****************************************************************************}
+
+ Constructor tai_ent.Create (const ProcName : String);
+
+ begin
+ Inherited Create;
+ Name:=ProcName;
+ typ:=ait_ent;
+ end;
+
+ Constructor tai_ent_end.Create (const ProcName : String);
+
+ begin
+ Inherited Create;
+ Name:=ProcName;
+ typ:=ait_ent_end;
+ end;
+
{****************************************************************************
TAI_CONST
diff --git a/mips/compiler/aggas.pas b/mips/compiler/aggas.pas
index e64d96a1ba..d9dfb03db9 100644
--- a/mips/compiler/aggas.pas
+++ b/mips/compiler/aggas.pas
@@ -1177,14 +1177,6 @@ implementation
else
AsmWriteln(tai_symbol(hp).sym.name);
end;
- if target_info.system in [system_mipsel_linux,system_mipseb_linux] then
- begin
- AsmWrite(#9'.ent'#9);
- if replaceforbidden then
- AsmWriteln(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
- else
- AsmWriteln(tai_symbol(hp).sym.name);
- end;
if (target_info.system = system_powerpc64_linux) and
(tai_symbol(hp).sym.typ = AT_FUNCTION) then
begin
@@ -1255,13 +1247,23 @@ implementation
AsmWriteLn(#9'.thumb_func');
end;
{$endif arm}
-{$if defined(alpha)}
ait_ent:
begin
- AsmWriteLn(#9'.ent'#9+tai_ent(hp).Name);
+ AsmWrite(#9'.ent'#9);
+ if replaceforbidden then
+ AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_ent(hp).Name))
+ else
+ AsmWriteLn(tai_ent(hp).Name);
+ end;
+ ait_ent_end:
+ begin
+ AsmWrite(#9'.end'#9);
+ if replaceforbidden then
+ AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_ent_end(hp).Name))
+ else
+ AsmWriteLn(tai_ent_end(hp).Name);
end;
-{$endif alpha}
- ait_symbol_end :
+ ait_symbol_end :
begin
if tf_needs_symbol_size in target_info.flags then
begin
@@ -1529,7 +1531,7 @@ implementation
i: longint;
begin
{$ifdef EXTDEBUG}
- if assigned(current_module.mainsource) then
+ if current_module.mainsource<>'' then
Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource);
{$endif}
@@ -1573,7 +1575,7 @@ implementation
AsmLn;
{$ifdef EXTDEBUG}
- if assigned(current_module.mainsource) then
+ if current_module.mainsource<>'' then
Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource);
{$endif EXTDEBUG}
end;
diff --git a/mips/compiler/alpha/aasmcpu.pas b/mips/compiler/alpha/aasmcpu.pas
index 6e1ef8d02b..9a9d1b5ec4 100644
--- a/mips/compiler/alpha/aasmcpu.pas
+++ b/mips/compiler/alpha/aasmcpu.pas
@@ -39,11 +39,6 @@ unit aasmcpu;
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);
@@ -260,14 +255,6 @@ implementation
LU:=L;
end;
- Constructor tai_ent.Create (const ProcName : String);
-
- begin
- Inherited Create;
- typ:=ait_ent;
- Name:=ProcName;
- end;
-
procedure InitAsm;
begin
end;
diff --git a/mips/compiler/aopt.pas b/mips/compiler/aopt.pas
index b763c9ddae..e0366d420d 100644
--- a/mips/compiler/aopt.pas
+++ b/mips/compiler/aopt.pas
@@ -298,7 +298,8 @@ Unit aopt;
Begin
if assigned(LabelInfo^.LabelTable) then
Freemem(LabelInfo^.LabelTable);
- Dispose(LabelInfo)
+ Dispose(LabelInfo);
+ inherited Destroy;
End;
diff --git a/mips/compiler/aoptbase.pas b/mips/compiler/aoptbase.pas
index a60c163585..fa511bbdf3 100644
--- a/mips/compiler/aoptbase.pas
+++ b/mips/compiler/aoptbase.pas
@@ -129,7 +129,11 @@ unit aoptbase;
Begin
Case op.typ Of
Top_Reg: RegInOp := Reg = op.reg;
- Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
+ Top_Ref: RegInOp := RegInRef(Reg, op.ref^);
+ {$ifdef arm}
+ Top_Shifterop: RegInOp := op.shifterop^.rs = Reg;
+ Top_RegSet: RegInOp := getsupreg(Reg) in op.regset^;
+ {$endif arm}
Else RegInOp := False
End
End;
diff --git a/mips/compiler/aoptobj.pas b/mips/compiler/aoptobj.pas
index e27009d3d3..c279e2af10 100644
--- a/mips/compiler/aoptobj.pas
+++ b/mips/compiler/aoptobj.pas
@@ -61,7 +61,7 @@ Unit AoptObj;
TRegArray = Array[byte] of tsuperregister;
- TRegSet = Set of byte;
+ TRegSet = tcpuregisterset;
{ possible actions on an operand: read, write or modify (= read & write) }
TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
diff --git a/mips/compiler/arm/aasmcpu.pas b/mips/compiler/arm/aasmcpu.pas
index 9db5726c2e..46309d56b0 100644
--- a/mips/compiler/arm/aasmcpu.pas
+++ b/mips/compiler/arm/aasmcpu.pas
@@ -567,10 +567,12 @@ implementation
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))
+ result:=(
+ ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
+ ((opcode=A_MVF) and (regtype = R_FPUREGISTER)) or
+ ((opcode in [A_FCPYS, A_FCPYD]) and (regtype = R_MMREGISTER))
) and
+ (oppostfix in [PF_None,PF_D]) and
(condition=C_None) and
(ops=2) and
(oper[0]^.typ=top_reg) and
diff --git a/mips/compiler/arm/agarmgas.pas b/mips/compiler/arm/agarmgas.pas
index 71a36f86bb..68d44706a6 100644
--- a/mips/compiler/arm/agarmgas.pas
+++ b/mips/compiler/arm/agarmgas.pas
@@ -153,7 +153,10 @@ unit agarmgas;
s:=s+gas_regname(index);
- if shiftmode<>SM_None then
+ {RRX always rotates by 1 bit and does not take an imm}
+ if shiftmode = SM_RRX then
+ s:=s+', rrx'
+ else if shiftmode <> SM_None then
s:=s+', '+gas_shiftmode2str[shiftmode]+' #'+tostr(shiftimm);
end
else if offset<>0 then
@@ -171,10 +174,6 @@ unit agarmgas;
getreferencestring:=s;
end;
-
- const
- shiftmode2str: array[tshiftmode] of string[3] = ('','lsl','lsr','asr','ror','rrx');
-
function getopstr(const o:toper) : string;
var
hs : string;
@@ -186,10 +185,13 @@ unit agarmgas;
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)
+ {RRX is special, it only rotates by 1 and does not take any shiftervalue}
+ if o.shifterop^.shiftmode=SM_RRX then
+ getopstr:='rrx'
+ else if (o.shifterop^.rs<>NR_NO) and (o.shifterop^.shiftimm=0) then
+ getopstr:=gas_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)
+ getopstr:=gas_shiftmode2str[o.shifterop^.shiftmode]+' #'+tostr(o.shifterop^.shiftimm)
else internalerror(200308282);
end;
top_const:
diff --git a/mips/compiler/arm/aoptcpu.pas b/mips/compiler/arm/aoptcpu.pas
index ab7ee875b7..b1b76c57af 100644
--- a/mips/compiler/arm/aoptcpu.pas
+++ b/mips/compiler/arm/aoptcpu.pas
@@ -66,6 +66,7 @@ Implementation
result:=
(p.typ=ait_instruction) and
(taicpu(p).condition=C_None) and
+ (taicpu(p).opcode<>A_PLD) and
((taicpu(p).opcode<>A_BLX) or
(taicpu(p).oper[0]^.typ=top_reg));
end;
@@ -96,12 +97,20 @@ Implementation
function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline;
begin
- result := (oper1.typ = oper2.typ) and
- (
- ((oper1.typ = top_const) and (oper1.val = oper2.val)) or
- ((oper1.typ = top_reg) and (oper1.reg = oper2.reg)) or
- ((oper1.typ = top_conditioncode) and (oper1.cc = oper2.cc))
- );
+ result := oper1.typ = oper2.typ;
+
+ if result then
+ case oper1.typ of
+ top_const:
+ Result:=oper1.val = oper2.val;
+ top_reg:
+ Result:=oper1.reg = oper2.reg;
+ top_conditioncode:
+ Result:=oper1.cc = oper2.cc;
+ top_ref:
+ Result:=RefsEqual(oper1.ref^, oper2.ref^);
+ else Result:=false;
+ end
end;
function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline;
@@ -130,24 +139,47 @@ Implementation
if not ((assigned(hp)) and (hp.typ = ait_instruction)) then
exit;
- {These are not writing to their first oper}
- if p.opcode in [A_STR, A_STRB, A_STRH, A_CMP, A_CMN, A_TST, A_TEQ,
- A_B, A_BL, A_BX, A_BLX] then
+ case p.opcode of
+ { These operands do not write into a register at all }
+ A_CMP, A_CMN, A_TST, A_TEQ, A_B, A_BL, A_BX, A_BLX, A_SWI, A_MSR, A_PLD:
+ exit;
+ {Take care of post/preincremented store and loads, they will change their base register}
+ A_STR, A_LDR:
+ regLoadedWithNewValue :=
+ (taicpu(p).oper[1]^.typ=top_ref) and
+ (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
+ (taicpu(p).oper[1]^.ref^.base = reg);
+ { These four are writing into the first 2 register, UMLAL and SMLAL will also read from them }
+ A_UMLAL, A_UMULL, A_SMLAL, A_SMULL:
+ regLoadedWithNewValue :=
+ (p.oper[1]^.typ = top_reg) and
+ (p.oper[1]^.reg = reg);
+ {Loads to oper2 from coprocessor}
+ {
+ MCR/MRC is currently not supported in FPC
+ A_MRC:
+ regLoadedWithNewValue :=
+ (p.oper[2]^.typ = top_reg) and
+ (p.oper[2]^.reg = reg);
+ }
+ {Loads to all register in the registerset}
+ A_LDM:
+ regLoadedWithNewValue := (getsupreg(reg) in p.oper[1]^.regset^);
+ end;
+
+ if regLoadedWithNewValue then
exit;
- { These four are writing into the first 2 register, UMLAL and SMLAL will also read from them }
- if (p.opcode in [A_UMLAL, A_UMULL, A_SMLAL, A_SMULL]) and
- (p.oper[1]^.typ = top_reg) and
- (p.oper[1]^.reg = reg) then
- begin
- regLoadedWithNewValue := true;
- exit
+ case p.oper[0]^.typ of
+ {This is the case}
+ top_reg:
+ regLoadedWithNewValue := (p.oper[0]^.reg = reg);
+ {LDM/STM might write a new value to their index register}
+ top_ref:
+ regLoadedWithNewValue :=
+ (taicpu(p).oper[0]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
+ (taicpu(p).oper[0]^.ref^.base = reg);
end;
-
- {All other instructions use oper[0] as destination}
- regLoadedWithNewValue :=
- (p.oper[0]^.typ = top_reg) and
- (p.oper[0]^.reg = reg);
end;
function instructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
@@ -162,7 +194,8 @@ Implementation
i:=1;
{For these instructions we have to start on oper[0]}
- if (p.opcode in [A_STR, A_STRB, A_STRH, A_CMP, A_CMN, A_TST, A_TEQ,
+ if (p.opcode in [A_STR, A_LDM, A_STM, A_PLD,
+ A_CMP, A_CMN, A_TST, A_TEQ,
A_B, A_BL, A_BX, A_BLX,
A_SMLAL, A_UMLAL]) then i:=0;
@@ -231,6 +264,12 @@ Implementation
i: longint;
TmpUsedRegs: TAllUsedRegs;
tempop: tasmop;
+
+ function IsPowerOf2(const value: DWord): boolean; inline;
+ begin
+ Result:=(value and (value - 1)) = 0;
+ end;
+
begin
result := false;
case p.typ of
@@ -432,6 +471,40 @@ Implementation
result := true;
end;
end;
+ { Change the common
+ mov r0, r0, lsr #24
+ and r0, r0, #255
+
+ and remove the superfluous and
+
+ This could be extended to handle more cases.
+ }
+ if (taicpu(p).ops=3) and
+ (taicpu(p).oper[2]^.typ = top_shifterop) and
+ (taicpu(p).oper[2]^.shifterop^.rs = NR_NO) and
+ (taicpu(p).oper[2]^.shifterop^.shiftmode = SM_LSR) and
+ (taicpu(p).oper[2]^.shifterop^.shiftimm >= 24 ) and
+ getnextinstruction(p,hp1) and
+ MatchInstruction(hp1, A_AND, [taicpu(p).condition], [taicpu(p).oppostfix]) and
+ (taicpu(hp1).ops=3) and
+ MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
+ MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[1]^) and
+ (taicpu(hp1).oper[2]^.typ = top_const) and
+ { Check if the AND actually would only mask out bits beeing already zero because of the shift
+ For LSR #25 and an AndConst of 255 that whould go like this:
+ 255 and ((2 shl (32-25))-1)
+ which results in 127, which is one less a power-of-2, meaning all lower bits are set.
+
+ LSR #25 and AndConst of 254:
+ 254 and ((2 shl (32-25))-1) = 126 -> lowest bit is clear, so we can't remove it.
+ }
+ ispowerof2((taicpu(hp1).oper[2]^.val and ((2 shl (32-taicpu(p).oper[2]^.shifterop^.shiftimm))-1))+1) then
+ begin
+ asml.insertbefore(tai_comment.Create(strpnew('Peephole LsrAnd2Lsr done')), hp1);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+
{
This changes the very common
mov r0, #0
diff --git a/mips/compiler/arm/cgcpu.pas b/mips/compiler/arm/cgcpu.pas
index 368cedf158..4822e00b97 100644
--- a/mips/compiler/arm/cgcpu.pas
+++ b/mips/compiler/arm/cgcpu.pas
@@ -211,9 +211,16 @@ unit cgcpu;
inherited init_register_allocators;
{ currently, we always save R14, 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_R12,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
- RS_R9,RS_R10,RS_R14],first_int_imreg,[])
+ begin
+ if assigned(current_procinfo) and (current_procinfo.framepointer<>NR_R11) then
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R12,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R14],first_int_imreg,[])
+ else
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R12,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R14],first_int_imreg,[])
+ end
else
{ r7 is not available on Darwin, it's used as frame pointer (always,
for backtrace support -- also in gcc/clang -> R11 can be used).
@@ -253,6 +260,7 @@ unit cgcpu;
imm_shift : byte;
l : tasmlabel;
hr : treference;
+ imm1, imm2: DWord;
begin
if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
internalerror(2002090902);
@@ -261,20 +269,16 @@ unit cgcpu;
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
+ else if (split_into_shifter_const(a,imm1, imm2)) 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)));
+ list.concat(taicpu.op_reg_const(A_MOV,reg, imm1));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg, imm2));
end
- else if (is_shifter_const(a-word(a),imm_shift)) and (is_shifter_const(word(a),imm_shift)) then
+ { loading of constants with mvn and bic }
+ else if (split_into_shifter_const(not(a), imm1, imm2)) 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));
+ list.concat(taicpu.op_reg_const(A_MVN,reg, imm1));
+ list.concat(taicpu.op_reg_reg_const(A_BIC,reg,reg, imm2));
end
else
begin
@@ -584,23 +588,34 @@ unit cgcpu;
procedure tcgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ var
+ so : tshifterop;
begin
- case op of
- OP_NEG:
- list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
- OP_NOT:
- begin
+ if op = OP_NEG then
+ list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0))
+ else if op = OP_NOT then
+ begin
+ if size in [OS_8, OS_16, OS_S8, OS_S16] then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSL;
+ if size in [OS_8, OS_S8] then
+ so.shiftimm:=24
+ else
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MVN,dst,src,so));
+ {Using a shift here allows this to be folded into another instruction}
+ if size in [OS_S8, OS_S16] then
+ so.shiftmode:=SM_ASR
+ else
+ so.shiftmode:=SM_LSR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,dst,so));
+ end
+ else
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
+ end
+ else
a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
- end;
end;
@@ -627,6 +642,17 @@ unit cgcpu;
a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
end;
+ function opshift2shiftmode(op: TOpCg): tshiftmode;
+ begin
+ case op of
+ OP_SHL: Result:=SM_LSL;
+ OP_SHR: Result:=SM_LSR;
+ OP_ROR: Result:=SM_ROR;
+ OP_ROL: Result:=SM_ROR;
+ OP_SAR: Result:=SM_ASR;
+ else internalerror(2012070501);
+ end
+ 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
@@ -634,6 +660,9 @@ unit cgcpu;
tmpreg : tregister;
so : tshifterop;
l1 : longint;
+ imm1, imm2: DWord;
+
+
begin
ovloc.loc:=LOC_VOID;
if {$ifopt R+}(a<>-2147483648) and{$endif} is_shifter_const(-a,shift) then
@@ -654,71 +683,22 @@ unit cgcpu;
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_SHL,
+ OP_SHR,
+ OP_ROL,
+ OP_ROR,
OP_SAR:
begin
if a>32 then
- internalerror(200308298);
+ internalerror(200308294);
if a<>0 then
begin
shifterop_reset(so);
- so.shiftmode:=SM_ASR;
- so.shiftimm:=a;
+ so.shiftmode:=opshift2shiftmode(op);
+ if op = OP_ROL then
+ so.shiftimm:=32-a
+ else
+ so.shiftimm:=a;
list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
end
else
@@ -787,6 +767,18 @@ unit cgcpu;
broader range of shifterconstants.}
else if (op = OP_AND) and is_shifter_const(not(dword(a)),shift) then
list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,not(dword(a))))
+ else if (op = OP_AND) and split_into_shifter_const(not(dword(a)), imm1, imm2) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_BIC,dst,src,imm1));
+ list.concat(taicpu.op_reg_reg_const(A_BIC,dst,dst,imm2));
+ end
+ else if (op in [OP_ADD, OP_SUB, OP_OR]) and
+ not(cgsetflags or setflags) and
+ split_into_shifter_const(a, imm1, imm2) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,imm1));
+ list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,dst,imm2));
+ end
else
begin
tmpreg:=getintregister(list,size);
@@ -809,25 +801,16 @@ unit cgcpu;
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:
+ OP_SHL,
+ OP_SHR,
+ OP_SAR,
+ OP_ROR:
begin
+ if (op = OP_ROR) and not(size in [OS_32,OS_S32]) then
+ internalerror(2008072801);
shifterop_reset(so);
so.rs:=src1;
- so.shiftmode:=SM_ASR;
+ so.shiftmode:=opshift2shiftmode(op);
list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
end;
OP_ROL:
@@ -836,19 +819,9 @@ unit cgcpu;
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);
+ list.concat(taicpu.op_reg_reg_const(A_RSB,tmpreg,src1, 32));
shifterop_reset(so);
- so.rs:=src1;
+ so.rs:=tmpreg;
so.shiftmode:=SM_ROR;
list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
end;
@@ -1942,10 +1915,10 @@ unit cgcpu;
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);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,ptrsinttype,paraloc3);
+ a_load_const_cgpara(list,OS_SINT,len,paraloc3);
a_loadaddr_ref_cgpara(list,dest,paraloc2);
a_loadaddr_ref_cgpara(list,source,paraloc1);
paramanager.freecgpara(list,paraloc3);
@@ -2639,7 +2612,7 @@ unit cgcpu;
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];
+ overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NEG];
begin
if (op in overflowops) and
(size in [OS_8,OS_S8,OS_16,OS_S16]) then
diff --git a/mips/compiler/arm/cpubase.pas b/mips/compiler/arm/cpubase.pas
index 46ca1d2705..fe0fd5c19f 100644
--- a/mips/compiler/arm/cpubase.pas
+++ b/mips/compiler/arm/cpubase.pas
@@ -314,7 +314,7 @@ unit cpubase;
(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);
+ 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
@@ -347,6 +347,7 @@ unit cpubase;
function is_pc(const r : tregister) : boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
+ function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword):boolean;
function dwarf_reg(r:tregister):shortint;
implementation
@@ -497,12 +498,6 @@ unit cpubase;
end;
- function rotl(d : dword;b : byte) : dword; {$ifdef USEINLINE}inline;{$endif USEINLINE}
- 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;
@@ -523,7 +518,7 @@ unit cpubase;
begin
for i:=0 to 15 do
begin
- if (dword(d) and not(rotl($ff,i*2)))=0 then
+ if (dword(d) and not(roldword($ff,i*2)))=0 then
begin
imm_shift:=i*2;
result:=true;
@@ -534,6 +529,30 @@ unit cpubase;
result:=false;
end;
+ function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword) : boolean;
+ var
+ d, i, i2: Dword;
+ begin
+ Result:=false;
+ {Thumb2 is not supported (YET?)}
+ if current_settings.cputype in cpu_thumb2 then exit;
+ d:=DWord(value);
+ for i:=0 to 15 do
+ begin
+ imm1:=d and rordword($FF, I*2);
+ imm2:=d and not (imm1); {remove already found bits}
+ {is the remainder a shifterconst? YAY! we've done it!}
+ {Could we start from i instead of 0?}
+ for i2:=0 to 15 do
+ begin
+ if (imm2 and not(rordword($FF,i2*2)))=0 then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+ end;
function dwarf_reg(r:tregister):shortint;
begin
diff --git a/mips/compiler/arm/cpupara.pas b/mips/compiler/arm/cpupara.pas
index 2ab9f9ec2f..2d6f2e5b9d 100644
--- a/mips/compiler/arm/cpupara.pas
+++ b/mips/compiler/arm/cpupara.pas
@@ -39,7 +39,7 @@ unit cpupara;
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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -79,16 +79,17 @@ unit cpupara;
end;
- procedure tarmparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ procedure tarmparamanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
begin
if nr<1 then
internalerror(2002070801);
cgpara.reset;
- cgpara.size:=OS_ADDR;
- cgpara.intsize:=sizeof(pint);
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -356,12 +357,9 @@ unit cpupara;
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
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
- paradef:=voidpointertype;
+ paradef:=getpointerdef(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@@ -384,7 +382,8 @@ unit cpupara;
if (paracgsize=OS_NO) then
begin
paracgsize:=OS_ADDR;
- paralen := tcgsize2size[OS_ADDR];
+ paralen:=tcgsize2size[OS_ADDR];
+ paradef:=voidpointertype;
end;
end
end;
@@ -392,6 +391,7 @@ unit cpupara;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].Alignment:=std_param_align;
hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
firstparaloc:=true;
{$ifdef EXTDEBUG}
@@ -587,38 +587,8 @@ unit cpupara;
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;
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
paraloc:=result.add_location;
{ Return in FPU register? }
diff --git a/mips/compiler/arm/cpupi.pas b/mips/compiler/arm/cpupi.pas
index c5c6a92eed..2815b09c6b 100644
--- a/mips/compiler/arm/cpupi.pas
+++ b/mips/compiler/arm/cpupi.pas
@@ -50,7 +50,7 @@ unit cpupi;
aasmtai,aasmdata,
tgobj,
symconst,symsym,paramgr,
- cgbase,
+ cgbase,cgutils,
cgobj;
procedure tarmprocinfo.set_first_temp_offset;
diff --git a/mips/compiler/arm/narminl.pas b/mips/compiler/arm/narminl.pas
index e23b726232..951698165a 100644
--- a/mips/compiler/arm/narminl.pas
+++ b/mips/compiler/arm/narminl.pas
@@ -49,6 +49,7 @@ interface
procedure second_sin_real; override;
}
procedure second_prefetch; override;
+ procedure second_abs_long; override;
private
procedure load_fpu_location(out singleprec: boolean);
end;
@@ -59,14 +60,14 @@ implementation
uses
globtype,systems,
cutils,verbose,globals,fmodule,
- cpuinfo,
+ cpuinfo, defutil,
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;
+ tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu,cgcpu, hlcgobj;
{*****************************************************************************
tarminlinenode
@@ -338,6 +339,21 @@ implementation
end;
end;
+ procedure tarminlinenode.second_abs_long;
+ var
+ hregister : tregister;
+ opsize : tcgsize;
+ hp : taicpu;
+ begin
+ secondpass(left);
+ opsize:=def_cgsize(left.resultdef);
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ location:=left.location;
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MOV,location.register,left.location.register), PF_S));
+ current_asmdata.CurrAsmList.concat(setcondition(taicpu.op_reg_reg_const(A_RSB,location.register,location.register, 0), C_MI));
+ end;
begin
cinlinenode:=tarminlinenode;
diff --git a/mips/compiler/arm/narmmat.pas b/mips/compiler/arm/narmmat.pas
index a2e244fd47..b18b9c5509 100644
--- a/mips/compiler/arm/narmmat.pas
+++ b/mips/compiler/arm/narmmat.pas
@@ -42,6 +42,10 @@ interface
procedure second_float;override;
end;
+ tarmshlshrnode = class(tcgshlshrnode)
+ procedure second_64bit;override;
+ function first_shlshr64bitint: tnode; override;
+ end;
implementation
@@ -350,9 +354,142 @@ implementation
end;
end;
+ function tarmshlshrnode.first_shlshr64bitint: tnode;
+ begin
+ result := nil;
+ end;
+
+ procedure tarmshlshrnode.second_64bit;
+ var
+ hreg64hi,hreg64lo,shiftreg:Tregister;
+ v : TConstExprInt;
+ l1,l2,l3:Tasmlabel;
+ so: tshifterop;
+
+ procedure emit_instr(p: tai);
+ begin
+ current_asmdata.CurrAsmList.concat(p);
+ end;
+
+ {Reg1 gets shifted and moved into reg2, and is set to zero afterwards}
+ procedure shift_more_than_32(reg1, reg2: TRegister; shiftval: Byte ; sm: TShiftMode);
+ begin
+ shifterop_reset(so); so.shiftimm:=shiftval - 32; so.shiftmode:=sm;
+ emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg1, so));
+ emit_instr(taicpu.op_reg_const(A_MOV, reg1, 0));
+ end;
+
+ procedure shift_less_than_32(reg1, reg2: TRegister; shiftval: Byte; shiftright: boolean);
+ begin
+ shifterop_reset(so); so.shiftimm:=shiftval;
+ if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
+ emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg1, reg1, so));
+
+ if shiftright then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR;
+ so.shiftimm:=32-shiftval;
+ emit_instr(taicpu.op_reg_reg_reg_shifterop(A_ORR, reg1, reg1, reg2, so));
+
+ if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
+ so.shiftimm:=shiftval;
+ emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg2, so));
+ end;
+
+ procedure shift_by_variable(reg1, reg2, shiftval: TRegister; shiftright: boolean);
+ var
+ shiftval2:TRegister;
+ begin
+ shifterop_reset(so);
+ shiftval2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ {Do we shift more than 32 bits?}
+ emit_instr(setoppostfix(taicpu.op_reg_reg_const(A_RSB, shiftval2, shiftval, 32), PF_S));
+
+ {This part cares for 32 bits and more}
+ emit_instr(setcondition(taicpu.op_reg_reg_const(A_SUB, shiftval2, shiftval, 32), C_MI));
+ if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
+ so.rs:=shiftval2;
+ emit_instr(setcondition(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg1, so), C_MI));
+
+ {Less than 32 bits}
+ so.rs:=shiftval;
+ emit_instr(setcondition(taicpu.op_reg_reg_shifterop(A_MOV, reg2, reg2, so), C_PL));
+ if shiftright then so.shiftmode:=SM_LSL else so.shiftmode:=SM_LSR;
+ so.rs:=shiftval2;
+ emit_instr(setcondition(taicpu.op_reg_reg_reg_shifterop(A_ORR, reg2, reg2, reg1, so), C_PL));
+
+ {Final adjustments}
+ if shiftright then so.shiftmode:=SM_LSR else so.shiftmode:=SM_LSL;
+ so.rs:=shiftval;
+ emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, reg1, reg1, so));
+ end;
+
+ begin
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+
+ { load left operator in a register }
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);
+ hreg64hi:=left.location.register64.reghi;
+ hreg64lo:=left.location.register64.reglo;
+ location.register64.reghi:=hreg64hi;
+ location.register64.reglo:=hreg64lo;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ v:=Tordconstnode(right).value and 63;
+ {Single bit shift}
+ if v = 1 then
+ if nodetype=shln then
+ begin
+ {Shift left by one by 2 simple 32bit additions}
+ emit_instr(setoppostfix(taicpu.op_reg_reg_reg(A_ADD, hreg64lo, hreg64lo, hreg64lo), PF_S));
+ emit_instr(taicpu.op_reg_reg_reg(A_ADC, hreg64hi, hreg64hi, hreg64hi));
+ end
+ else
+ begin
+ {Shift right by first shifting hi by one and then using RRX (rotate right extended), which rotates through the carry}
+ shifterop_reset(so); so.shiftmode:=SM_LSR; so.shiftimm:=1;
+ emit_instr(setoppostfix(taicpu.op_reg_reg_shifterop(A_MOV, hreg64hi, hreg64hi, so), PF_S));
+ so.shiftmode:=SM_RRX; so.shiftimm:=0; {RRX does NOT have a shift amount}
+ emit_instr(taicpu.op_reg_reg_shifterop(A_MOV, hreg64lo, hreg64lo, so));
+ end
+ {A 32bit shift just replaces a register and clears the other}
+ else if v = 32 then
+ begin
+ if nodetype=shln then
+ emit_instr(taicpu.op_reg_const(A_MOV, hreg64hi, 0))
+ else
+ emit_instr(taicpu.op_reg_const(A_MOV, hreg64lo, 0));
+ location.register64.reghi:=hreg64lo;
+ location.register64.reglo:=hreg64hi;
+ end
+ {Shift LESS than 32}
+ else if (v < 32) and (v > 1) then
+ if nodetype=shln then
+ shift_less_than_32(hreg64hi, hreg64lo, v.uvalue, false)
+ else
+ shift_less_than_32(hreg64lo, hreg64hi, v.uvalue, true)
+ {More than 32}
+ else if v > 32 then
+ if nodetype=shln then
+ shift_more_than_32(hreg64lo, hreg64hi, v.uvalue, SM_LSL)
+ else
+ shift_more_than_32(hreg64hi, hreg64lo, v.uvalue, SM_LSR);
+ end
+ else
+ begin
+ { force right operators in a register }
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,false);
+ if nodetype = shln then
+ shift_by_variable(hreg64lo,hreg64hi,right.location.register, false)
+ else
+ shift_by_variable(hreg64hi,hreg64lo,right.location.register, true);
+ end;
+ end;
+
begin
cmoddivnode:=tarmmoddivnode;
cnotnode:=tarmnotnode;
cunaryminusnode:=tarmunaryminusnode;
+ cshlshrnode:=tarmshlshrnode;
end.
diff --git a/mips/compiler/arm/raarmgas.pas b/mips/compiler/arm/raarmgas.pas
index 0ad94a2f20..91b8c816b7 100644
--- a/mips/compiler/arm/raarmgas.pas
+++ b/mips/compiler/arm/raarmgas.pas
@@ -62,7 +62,7 @@ Unit raarmgas;
procinfo,
itcpugas,
rabase,rautils,
- cgbase,cgobj
+ cgbase,cgutils,cgobj
;
diff --git a/mips/compiler/assemble.pas b/mips/compiler/assemble.pas
index 689f39f9c3..324fffd672 100644
--- a/mips/compiler/assemble.pas
+++ b/mips/compiler/assemble.pas
@@ -604,6 +604,14 @@ Implementation
Replace(result,'$ASM',maybequoted(AsmFileName));
Replace(result,'$OBJ',maybequoted(ObjFileName));
end;
+ if (cs_create_pic in current_settings.moduleswitches) then
+ Replace(result,'$PIC','-KPIC')
+ else
+ Replace(result,'$PIC','');
+ if (cs_asm_source in current_settings.globalswitches) then
+ Replace(result,'$NOWARN','')
+ else
+ Replace(result,'$NOWARN','-W');
end;
diff --git a/mips/compiler/avr/cgcpu.pas b/mips/compiler/avr/cgcpu.pas
index 21d0d8a5b5..a7ce99033f 100644
--- a/mips/compiler/avr/cgcpu.pas
+++ b/mips/compiler/avr/cgcpu.pas
@@ -470,9 +470,9 @@ unit cgcpu;
paraloc1.init;
paraloc2.init;
paraloc3.init;
- paramanager.getintparaloc(pocall_default,1,paraloc1);
- paramanager.getintparaloc(pocall_default,2,paraloc2);
- paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.getintparaloc(pocall_default,1,u16inttype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,u16inttype,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,pasbool8type,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);
@@ -1451,10 +1451,10 @@ unit cgcpu;
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);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,ptrsinttype,paraloc3);
+ a_load_const_cgpara(list,OS_SINT,len,paraloc3);
a_loadaddr_ref_cgpara(list,dest,paraloc2);
a_loadaddr_ref_cgpara(list,source,paraloc1);
paramanager.freecgpara(list,paraloc3);
diff --git a/mips/compiler/avr/cpubase.pas b/mips/compiler/avr/cpubase.pas
index 2b02b97751..b0a3ba014f 100644
--- a/mips/compiler/avr/cpubase.pas
+++ b/mips/compiler/avr/cpubase.pas
@@ -101,11 +101,11 @@ unit cpubase;
{ Float Super register first and last }
first_fpu_supreg = RS_INVALID;
- first_fpu_imreg = RS_INVALID;
+ first_fpu_imreg = 0;
{ MM Super register first and last }
first_mm_supreg = RS_INVALID;
- first_mm_imreg = RS_INVALID;
+ first_mm_imreg = 0;
regnumber_count_bsstart = 32;
diff --git a/mips/compiler/avr/cpupara.pas b/mips/compiler/avr/cpupara.pas
index d313d24896..ae5c5a5996 100644
--- a/mips/compiler/avr/cpupara.pas
+++ b/mips/compiler/avr/cpupara.pas
@@ -38,7 +38,7 @@ unit cpupara;
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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -69,16 +69,17 @@ unit cpupara;
end;
- procedure tavrparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ procedure tavrparamanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -271,12 +272,9 @@ unit cpupara;
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
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
- paradef:=voidpointertype;
+ paradef:=getpointerdef(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@@ -299,7 +297,8 @@ unit cpupara;
if (paracgsize=OS_NO) then
begin
paracgsize:=OS_ADDR;
- paralen := tcgsize2size[OS_ADDR];
+ paralen:=tcgsize2size[OS_ADDR];
+ paradef:=voidpointertype;
end;
end
end;
@@ -307,6 +306,7 @@ unit cpupara;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].Alignment:=std_param_align;
hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
{$ifdef EXTDEBUG}
if paralen=0 then
@@ -415,38 +415,8 @@ unit cpupara;
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;
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
paraloc:=result.add_location;
{ Return in FPU register? }
diff --git a/mips/compiler/avr/raavrgas.pas b/mips/compiler/avr/raavrgas.pas
index 3cefacaedf..967f9e742b 100644
--- a/mips/compiler/avr/raavrgas.pas
+++ b/mips/compiler/avr/raavrgas.pas
@@ -59,7 +59,7 @@ Unit raavrgas;
procinfo,
itcpugas,
rabase,rautils,
- cgbase,cgobj
+ cgbase,cgutils,cgobj
;
diff --git a/mips/compiler/cgbase.pas b/mips/compiler/cgbase.pas
index 26a1ac6aee..abd47adf6d 100644
--- a/mips/compiler/cgbase.pas
+++ b/mips/compiler/cgbase.pas
@@ -220,7 +220,6 @@ interface
end;
{ Set type definition for registers }
- tcpuregisterset = set of byte;
tsuperregisterset = array[byte] of set of byte;
pmmshuffle = ^tmmshuffle;
@@ -264,10 +263,6 @@ interface
{ 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,
diff --git a/mips/compiler/cgobj.pas b/mips/compiler/cgobj.pas
index 674623deb5..ec1cc20bde 100644
--- a/mips/compiler/cgobj.pas
+++ b/mips/compiler/cgobj.pas
@@ -390,21 +390,6 @@ unit cgobj;
}
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 overflow checking code for a node }
procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); virtual;abstract;
@@ -2066,239 +2051,6 @@ implementation
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_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
begin
g_overflowCheck(list,loc,def);
@@ -2329,8 +2081,8 @@ implementation
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.getintparaloc(pocall_default,1,s32inttype,cgpara1);
+ a_load_const_cgpara(list,OS_S32,tcgint(210),cgpara1);
paramanager.freecgpara(list,cgpara1);
a_call_name(list,'FPC_HANDLEERROR',false);
a_label(list,oklabel);
@@ -2346,10 +2098,10 @@ implementation
begin
cgpara1.init;
cgpara2.init;
- paramanager.getintparaloc(pocall_default,1,cgpara1);
- paramanager.getintparaloc(pocall_default,2,cgpara2);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,cgpara1);
if (cs_check_object in current_settings.localswitches) then
begin
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,cgpara2);
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);
@@ -2406,7 +2158,7 @@ implementation
{ do getmem call }
cgpara1.init;
- paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,1,ptruinttype,cgpara1);
a_load_reg_cgpara(list,OS_INT,sizereg,cgpara1);
paramanager.freecgpara(list,cgpara1);
allocallcpuregisters(list);
@@ -2420,11 +2172,11 @@ implementation
cgpara1.init;
cgpara2.init;
cgpara3.init;
- paramanager.getintparaloc(pocall_default,1,cgpara1);
- paramanager.getintparaloc(pocall_default,2,cgpara2);
- paramanager.getintparaloc(pocall_default,3,cgpara3);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,ptrsinttype,cgpara3);
{ load size }
- a_load_reg_cgpara(list,OS_INT,sizereg,cgpara3);
+ a_load_reg_cgpara(list,OS_SINT,sizereg,cgpara3);
{ load destination }
a_load_reg_cgpara(list,OS_ADDR,destreg,cgpara2);
{ load source }
@@ -2447,7 +2199,7 @@ implementation
begin
{ do move call }
cgpara1.init;
- paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,cgpara1);
{ load source }
a_load_loc_cgpara(list,l,cgpara1);
paramanager.freecgpara(list,cgpara1);
@@ -2507,12 +2259,19 @@ implementation
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
+ { the array has to be declared even if no MM registers are saved
+ (such as with SSE on i386), and since 0-element arrays don't
+ exist, they contain a single RS_INVALID element in that case
+ }
+ if saved_mm_registers[r]<>RS_INVALID 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]);
+ 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;
- include(rg[R_MMREGISTER].preserved_by_proc,saved_mm_registers[r]);
end;
end;
end;
diff --git a/mips/compiler/cgutils.pas b/mips/compiler/cgutils.pas
index 60a185c26f..76c60805fd 100644
--- a/mips/compiler/cgutils.pas
+++ b/mips/compiler/cgutils.pas
@@ -32,7 +32,17 @@ unit cgutils;
aasmbase,
cpubase,cgbase;
+ const
+ { implementation of max function using only functionality that can be
+ evaluated as a constant expression by the compiler -- this is
+ basically maxcpureg = max(max(first_int_imreg,first_fpu_imreg),first_mm_imreg)-1 }
+ tmpmaxcpufpuintreg = first_int_imreg + ((first_fpu_imreg - first_int_imreg) * ord(first_int_imreg < first_fpu_imreg));
+ maxcpuregister = (tmpmaxcpufpuintreg + ((first_mm_imreg - tmpmaxcpufpuintreg) * ord(tmpmaxcpufpuintreg < first_mm_imreg)))-1;
+
type
+ { Set type definition for cpuregisters }
+ tcpuregisterset = set of 0..maxcpuregister;
+
{$ifdef jvm}
tarrayreftype = (art_none,art_indexreg,art_indexref,art_indexconst);
{$endif jvm}
diff --git a/mips/compiler/cutils.pas b/mips/compiler/cutils.pas
index dc41ac209a..177d064a65 100644
--- a/mips/compiler/cutils.pas
+++ b/mips/compiler/cutils.pas
@@ -813,27 +813,11 @@ implementation
{
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;
+ if (value = 0) or (value and (value - 1) <> 0) then
+ exit(false);
+ power:=BsfQWord(value);
+ result:=true;
end;
diff --git a/mips/compiler/dbgstabs.pas b/mips/compiler/dbgstabs.pas
index 103cba1c87..2057de8ceb 100644
--- a/mips/compiler/dbgstabs.pas
+++ b/mips/compiler/dbgstabs.pas
@@ -149,11 +149,38 @@ implementation
uses
SysUtils,cutils,cfileutl,
globals,globtype,verbose,constexp,
- defutil,
- cpuinfo,cpubase,paramgr,
+ defutil, cgutils, parabase,
+ cpuinfo,cpubase,cpupi,paramgr,
aasmbase,procinfo,
finput,fmodule,ppu;
+
+ const
+ current_procdef : tprocdef = nil;
+
+ function GetOffsetStr(reference : TReference) : string;
+ begin
+{$ifdef MIPS}
+ if (reference.index=NR_STACK_POINTER_REG) or
+ (reference.base=NR_STACK_POINTER_REG) then
+ GetOffsetStr:=tostr(reference.offset
+ - mips_extra_offset(current_procdef))
+ else
+{$endif MIPS}
+ GetOffsetStr:=tostr(reference.offset);
+ end;
+
+ function GetParaOffsetStr(reference : TCGParaReference) : string;
+ begin
+{$ifdef MIPS}
+ if reference.index=NR_STACK_POINTER_REG then
+ GetParaOffsetStr:=tostr(reference.offset
+ - mips_extra_offset(current_procdef))
+ else
+{$endif MIPS}
+ GetParaOffsetStr:=tostr(reference.offset);
+ end;
+
function GetSymName(Sym : TSymEntry) : string;
begin
if Not (cs_stabs_preservecase in current_settings.globalswitches) then
@@ -734,15 +761,15 @@ implementation
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),
+ '_PRIVATE:ar$1;1;64;$3,128,256;USERDATA:ar$1;1;32;$3,384,256;'+
+ 'NAME:ar$1;0;255;$4,640,2048;;',[def_stab_number(s32inttype),
def_stab_number(s64inttype),
def_stab_number(u8inttype),
def_stab_number(cansichartype)]);
{$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),
+ '_PRIVATE:ar$1;1;32;$3,96,256;USERDATA:ar$1;1;32;$2,352,256;'+
+ 'NAME:ar$1;0;255;$3,608,2048;;',[def_stab_number(s32inttype),
def_stab_number(u8inttype),
def_stab_number(cansichartype)]);
{$endif cpu64bitaddr}
@@ -1052,6 +1079,7 @@ implementation
var
hs : ansistring;
templist : TAsmList;
+ prev_procdef : tprocdef;
begin
if not(def.in_currentunit) or
{ happens for init procdef of units without init section }
@@ -1060,6 +1088,8 @@ implementation
{ mark as used so the local type defs also be written }
def.dbg_state:=dbg_state_used;
+ prev_procdef:=current_procdef;
+ current_procdef:=def;
templist:=gen_procdef_endsym_stabs(def);
current_asmdata.asmlists[al_procedures].insertlistafter(def.procendtai,templist);
@@ -1090,11 +1120,11 @@ implementation
hs:='X';
templist.concat(Tai_stab.create(stabsdir,strpnew(
'"'+GetSymName(def.procsym)+':'+hs+def_stab_number(def.returndef)+'",'+
- base_stabs_str(localvarsymref_stab,'0','0',tostr(tabstractnormalvarsym(def.funcretsym).localloc.reference.offset)))));
+ base_stabs_str(localvarsymref_stab,'0','0',getoffsetstr(tabstractnormalvarsym(def.funcretsym).localloc.reference)))));
if (m_result in current_settings.modeswitches) then
templist.concat(Tai_stab.create(stabsdir,strpnew(
'"RESULT:'+hs+def_stab_number(def.returndef)+'",'+
- base_stabs_str(localvarsymref_stab,'0','0',tostr(tabstractnormalvarsym(def.funcretsym).localloc.reference.offset)))));
+ base_stabs_str(localvarsymref_stab,'0','0',getoffsetstr(tabstractnormalvarsym(def.funcretsym).localloc.reference)))));
end;
end;
@@ -1102,6 +1132,7 @@ implementation
current_asmdata.asmlists[al_procedures].insertlistbefore(def.procstarttai,templist);
templist.free;
+ current_procdef:=prev_procdef;
end;
@@ -1256,7 +1287,7 @@ implementation
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",'+base_stabs_str(localvarsymref_stab,'0','${line}','$2'),[st,tostr(sym.localloc.reference.offset)])
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(localvarsymref_stab,'0','${line}','$2'),[st,getoffsetstr(sym.localloc.reference)])
else
internalerror(2003091814);
end;
@@ -1411,7 +1442,7 @@ implementation
begin
if (sym.localloc.loc=LOC_REFERENCE) then
ss:=sym_stabstr_evaluate(sym,'"pvmt:p$1",'+base_stabs_str(localvarsymref_stab,'0','0','$2'),
- [def_stab_number(pvmttype),tostr(sym.localloc.reference.offset)])
+ [def_stab_number(pvmttype),getoffsetstr(sym.localloc.reference)])
else
begin
regidx:=findreg_by_number(sym.localloc.register);
@@ -1427,7 +1458,7 @@ implementation
c:='p';
if (sym.localloc.loc=LOC_REFERENCE) then
ss:=sym_stabstr_evaluate(sym,'"$$t:$1",'+base_stabs_str(localvarsymref_stab,'0','0','$2'),
- [c+def_stab_number(tprocdef(sym.owner.defowner).struct),tostr(sym.localloc.reference.offset)])
+ [c+def_stab_number(tprocdef(sym.owner.defowner).struct),getoffsetstr(sym.localloc.reference)])
else
begin
if (c='p') then
@@ -1481,14 +1512,15 @@ implementation
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",'+base_stabs_str(localvarsymref_stab,'0','${line}','$2'),[c+st,tostr(sym.paraloc[calleeside].location^.reference.offset)]);
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(localvarsymref_stab,'0','${line}','$2'),
+ [c+st,getparaoffsetstr(sym.paraloc[calleeside].location^.reference)]);
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",'+base_stabs_str(paravarsymref_stab,'0','${line}','$2'),[c+st,tostr(sym.localloc.reference.offset)])
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(paravarsymref_stab,'0','${line}','$2'),[c+st,getoffsetstr(sym.localloc.reference)])
end;
else
internalerror(2003091814);
diff --git a/mips/compiler/defcmp.pas b/mips/compiler/defcmp.pas
index bc50dd2e29..b8267a01b5 100644
--- a/mips/compiler/defcmp.pas
+++ b/mips/compiler/defcmp.pas
@@ -1533,13 +1533,18 @@ implementation
doconv:=tc_variant_2_interface;
eq:=te_convert_l2;
end
- { ugly, but delphi allows it }
+ { ugly, but delphi allows it (enables typecasting ordinals/
+ enums of any size to pointer-based object defs) }
{ in Java enums /are/ class instances, and hence such
- typecasts must not be treated as integer-like conversions
+ typecasts must not be treated as integer-like conversions;
+ arbitrary constants cannot be converted into classes/
+ pointer-based values either on the JVM -> always return
+ false and let it be handled by the regular explicit type
+ casting code
}
- else if ((not(target_info.system in systems_jvm) and
- (def_from.typ=enumdef)) or
- (def_from.typ=orddef)) and
+ else if (not(target_info.system in systems_jvm) and
+ ((def_from.typ=enumdef) or
+ (def_from.typ=orddef))) and
(m_delphi in current_settings.modeswitches) and
(cdo_explicit in cdoptions) then
begin
diff --git a/mips/compiler/fpcdefs.inc b/mips/compiler/fpcdefs.inc
index 5374c4949b..d19cb94077 100644
--- a/mips/compiler/fpcdefs.inc
+++ b/mips/compiler/fpcdefs.inc
@@ -107,6 +107,7 @@
{$define cpumm}
{$define cpurox}
{$define cpurefshaveindexreg}
+ {$define fpc_compiler_has_fixup_jmps}
{$endif powerpc}
{$ifdef powerpc64}
@@ -117,6 +118,7 @@
{$define cpumm}
{$define cpurox}
{$define cpurefshaveindexreg}
+ {$define fpc_compiler_has_fixup_jmps}
{$endif powerpc64}
{$ifdef arm}
@@ -170,20 +172,32 @@
{$ifdef mipsel}
{$define mips}
+{$else not mipsel}
+ { Define both mips and mipseb if mipsel is not defined
+ but mips cpu is wanted. }
+ {$ifdef mipseb}
+ {$define mips}
+ {$endif mipseb}
+ {$ifdef mips}
+ {$define mipseb}
+ {$endif mips}
{$endif mipsel}
-{$ifdef mipseb}
- {$define mips}
-{$endif mipseb}
+
{$ifdef mips}
- {$define cpu32bit}
- {$define cpu32bitalu}
- {$define cpu32bitaddr}
+ {$ifndef mips64}
+ {$define cpu32bit}
+ {$define cpu32bitalu}
+ {$define cpu32bitaddr}
+ {$else}
+ {$error mips64 not yet supported}
+ {$endif}
{ define cpuflags}
{$define cputargethasfixedstack}
{$define cpurequiresproperalignment}
{ define cpumm}
{$define cpurefshaveindexreg}
+ {$define fpc_compiler_has_fixup_jmps}
{$endif mips}
{$ifdef jvm}
diff --git a/mips/compiler/fppu.pas b/mips/compiler/fppu.pas
index a01f646ee8..fb16cc2bfe 100644
--- a/mips/compiler/fppu.pas
+++ b/mips/compiler/fppu.pas
@@ -719,8 +719,6 @@ var
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
@@ -728,73 +726,78 @@ var
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
+ if sources_avail then
+ begin
+ if (flags and uf_in_library)<>0 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
+ sources_avail:=false;
+ temp:=' library';
+ end
+ else if pos('Macro ',hs)=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
+ { we don't want to find this file }
+ { but there is a problem with file indexing !! }
+ temp:='';
+ end
+ else
begin
- if is_main then
- main_dir:=ExtractFilePath(hs);
- temp:=' time '+filetimestring(source_time);
- if (orgfiletime<>-1) and
- (source_time<>orgfiletime) then
+ { 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
- do_compile:=true;
- recompile_reason:=rr_sourcenewer;
- Message2(unit_u_source_modified,hs,ppufilename,@queuecomment);
- temp:=temp+' *';
+ Source_Time:=GetNamedFileTime(main_dir+hs);
+ if Source_Time<>-1 then
+ hs:=main_dir+hs;
end;
- end
- else
- begin
- sources_avail:=false;
- temp:=' not found';
+ 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;
- hp:=tdosinputfile.create(hs);
- { the indexing is wrong here PM }
- sourcefiles.register_file(hp);
- end;
+ end
+ else
+ temp:=' not available';
if is_main then
begin
mainsource:=hs;
diff --git a/mips/compiler/globals.pas b/mips/compiler/globals.pas
index 4c41b4c7d8..c0fffb3e73 100644
--- a/mips/compiler/globals.pas
+++ b/mips/compiler/globals.pas
@@ -117,8 +117,11 @@ interface
type
- { this is written to ppus during token recording for generics so it must be packed }
- tsettings = packed record
+ { this is written to ppus during token recording for generics,
+ it used to required to be packed,
+ but this requirement is now obsolete,
+ as the fields are written one by one. PM 2012-06-13 }
+ tsettings = record
alignment : talignmentinfo;
globalswitches : tglobalswitches;
targetswitches : ttargetswitches;
diff --git a/mips/compiler/globtype.pas b/mips/compiler/globtype.pas
index f00730c832..e562792b91 100644
--- a/mips/compiler/globtype.pas
+++ b/mips/compiler/globtype.pas
@@ -212,7 +212,16 @@ interface
{ for the JVM target: generate integer array initializations via string
constants in order to reduce the generated code size (Java routines
are limited to 64kb of bytecode) }
- ts_compact_int_array_init
+ ts_compact_int_array_init,
+ { for the JVM target: intialize enum fields in constructors with the
+ enum class instance corresponding to ordinal value 0 (not done by
+ default because this initialization can only be performed after the
+ inherited constructors have run, and if they call a virtual method
+ of the current class, then this virtual method may already have
+ initialized that field with another value and the constructor
+ initialization will result in data loss }
+ ts_jvm_enum_field_init
+
);
ttargetswitches = set of ttargetswitch;
@@ -269,7 +278,8 @@ interface
TargetSwitchStr : array[ttargetswitch] of string[19] = ('',
'SMALLTOC',
- 'COMPACTINTARRAYINIT');
+ 'COMPACTINTARRAYINIT',
+ 'ENUMFIELDINIT');
{ switches being applied to all CPUs at the given level }
genericlevel1optimizerswitches = [cs_opt_level1];
diff --git a/mips/compiler/hlcg2ll.pas b/mips/compiler/hlcg2ll.pas
index 0086d212fc..1376cbbdb2 100644
--- a/mips/compiler/hlcg2ll.pas
+++ b/mips/compiler/hlcg2ll.pas
@@ -150,7 +150,7 @@ unit hlcg2ll;
@param(tosize type of the pointer that we get as a result)
@param(r reference to get address from)
}
- procedure a_loadaddr_ref_cgpara(list : TAsmList;fromsize, tosize : tdef;const r : treference;const cgpara : TCGPara);override;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;fromsize : tdef;const r : treference;const cgpara : TCGPara);override;
procedure a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; weak: boolean);override;
procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override;
@@ -278,21 +278,6 @@ unit hlcg2ll;
}
procedure g_concatcopy_unaligned(list : TAsmList;size: tdef; const source,dest : treference);override;
- {# 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;strdef:tstringdef);override;
- procedure g_copyvariant(list : TAsmList;const source,dest : treference;vardef:tvariantdef);override;
-
- procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
- procedure g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation;
- const name: string);override;
- procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);override;
- procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);override;
{# Generates overflow checking code for a node }
procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); override;
@@ -470,7 +455,7 @@ implementation
cg.a_load_loc_cgpara(list,l,cgpara);
end;
- procedure thlcg2ll.a_loadaddr_ref_cgpara(list: TAsmList; fromsize, tosize: tdef; const r: treference; const cgpara: TCGPara);
+ procedure thlcg2ll.a_loadaddr_ref_cgpara(list: TAsmList; fromsize: tdef; const r: treference; const cgpara: TCGPara);
begin
cg.a_loadaddr_ref_cgpara(list,r,cgpara);
end;
@@ -943,36 +928,6 @@ implementation
cg.g_concatcopy_unaligned(list,source,dest,size.size);
end;
- procedure thlcg2ll.g_copyshortstring(list: TAsmList; const source, dest: treference; strdef: tstringdef);
- begin
- cg.g_copyshortstring(list,source,dest,strdef.len);
- end;
-
- procedure thlcg2ll.g_copyvariant(list: TAsmList; const source, dest: treference; vardef: tvariantdef);
- begin
- cg.g_copyvariant(list,source,dest);
- end;
-
- procedure thlcg2ll.g_incrrefcount(list: TAsmList; t: tdef; const ref: treference);
- begin
- cg.g_incrrefcount(list,t,ref);
- end;
-
- procedure thlcg2ll.g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation; const name: string);
- begin
- cg.g_array_rtti_helper(list, t, ref, highloc, name);
- end;
-
- procedure thlcg2ll.g_initialize(list: TAsmList; t: tdef; const ref: treference);
- begin
- cg.g_initialize(list,t,ref);
- end;
-
- procedure thlcg2ll.g_finalize(list: TAsmList; t: tdef; const ref: treference);
- begin
- cg.g_finalize(list,t,ref);
- end;
-
procedure thlcg2ll.g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef);
begin
cg.g_overflowcheck(list,loc,def);
diff --git a/mips/compiler/hlcgobj.pas b/mips/compiler/hlcgobj.pas
index 5883bb264d..9cb1f8fbff 100644
--- a/mips/compiler/hlcgobj.pas
+++ b/mips/compiler/hlcgobj.pas
@@ -77,6 +77,16 @@ unit hlcgobj;
the cpu specific child cg object have such a method?}
function uses_registers(rt:Tregistertype):boolean; inline;
+ {# 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); inline;
procedure translate_register(var reg : tregister); inline;
@@ -161,7 +171,7 @@ unit hlcgobj;
@param(tosize type of the pointer that we get as a result)
@param(r reference to get address from)
}
- procedure a_loadaddr_ref_cgpara(list : TAsmList;fromsize, tosize : tdef;const r : treference;const cgpara : TCGPara);virtual;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;fromsize : tdef;const r : treference;const cgpara : TCGPara);virtual;
{ Remarks:
* If a method specifies a size you have only to take care
@@ -385,14 +395,14 @@ unit hlcgobj;
@param(dest Destination reference of copy)
}
- procedure g_copyshortstring(list : TAsmList;const source,dest : treference;strdef:tstringdef);virtual;abstract;
- procedure g_copyvariant(list : TAsmList;const source,dest : treference;vardef:tvariantdef);virtual;abstract;
+ procedure g_copyshortstring(list : TAsmList;const source,dest : treference;strdef:tstringdef);virtual;
+ procedure g_copyvariant(list : TAsmList;const source,dest : treference;vardef:tvariantdef);virtual;
- procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);virtual;abstract;
- procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);virtual;abstract;
- procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);virtual;abstract;
+ procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);virtual;
+ procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);virtual;
+ procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);virtual;
procedure g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation;
- const name: string);virtual;abstract;
+ const name: string);virtual;
{# Generates range checking code. It is to note
that this routine does not need to be overridden,
@@ -543,7 +553,7 @@ implementation
fmodule,export,
verbose,defutil,paramgr,
symbase,symsym,symtable,
- ncon,nld,pass_1,pass_2,
+ ncon,nld,ncgrtti,pass_1,pass_2,
cpuinfo,cgobj,tgobj,cutils,procinfo,
ncgutil,ngenutil;
@@ -624,6 +634,36 @@ implementation
result:=cg.uses_registers(rt);
end;
+ procedure thlcgobj.getcpuregister(list: TAsmList; r: Tregister);
+ begin
+ cg.getcpuregister(list,r);
+ end;
+
+ procedure thlcgobj.ungetcpuregister(list: TAsmList; r: Tregister);
+ begin
+ cg.ungetcpuregister(list,r);
+ end;
+
+ procedure thlcgobj.alloccpuregisters(list: TAsmList; rt: Tregistertype; const r: Tcpuregisterset);
+ begin
+ cg.alloccpuregisters(list,rt,r);
+ end;
+
+ procedure thlcgobj.dealloccpuregisters(list: TAsmList; rt: Tregistertype; const r: Tcpuregisterset);
+ begin
+ cg.dealloccpuregisters(list,rt,r);
+ end;
+
+ procedure thlcgobj.allocallcpuregisters(list: TAsmList);
+ begin
+ cg.allocallcpuregisters(list);
+ end;
+
+ procedure thlcgobj.deallocallcpuregisters(list: TAsmList);
+ begin
+ cg.deallocallcpuregisters(list);
+ end;
+
procedure thlcgobj.do_register_allocation(list: TAsmList; headertai: tai);
begin
cg.do_register_allocation(list,headertai);
@@ -731,8 +771,8 @@ implementation
LOC_FPUREGISTER,LOC_CFPUREGISTER:
begin
tg.gethltemp(list,size,size.size,tt_normal,ref);
- a_load_reg_ref(list,size,size,r,ref);
- a_loadfpu_ref_cgpara(list,size,ref,cgpara);
+ a_load_reg_ref(list,size,cgpara.def,r,ref);
+ a_loadfpu_ref_cgpara(list,cgpara.def,ref,cgpara);
tg.ungettemp(list,ref);
end
else
@@ -810,7 +850,7 @@ implementation
end;
end;
- procedure thlcgobj.a_loadaddr_ref_cgpara(list: TAsmList; fromsize, tosize: tdef; const r: treference; const cgpara: TCGPara);
+ procedure thlcgobj.a_loadaddr_ref_cgpara(list: TAsmList; fromsize: tdef; const r: treference; const cgpara: TCGPara);
var
hr : tregister;
begin
@@ -818,13 +858,13 @@ implementation
if cgpara.location^.loc in [LOC_CREGISTER,LOC_REGISTER] then
begin
paramanager.allocparaloc(list,cgpara.location);
- a_loadaddr_ref_reg(list,fromsize,tosize,r,cgpara.location^.register)
+ a_loadaddr_ref_reg(list,fromsize,cgpara.def,r,cgpara.location^.register)
end
else
begin
- hr:=getaddressregister(list,tosize);
- a_loadaddr_ref_reg(list,fromsize,tosize,r,hr);
- a_load_reg_cgpara(list,tosize,hr,cgpara);
+ hr:=getaddressregister(list,cgpara.def);
+ a_loadaddr_ref_reg(list,fromsize,cgpara.def,r,hr);
+ a_load_reg_cgpara(list,cgpara.def,hr,cgpara);
end;
end;
@@ -1039,7 +1079,7 @@ implementation
var
fromsubsetregdef,
tosubsetregdef: torddef;
- tmpreg: tregister;
+ tmpreg, tmpreg2: tregister;
bitmask: aword;
stopbit: byte;
begin
@@ -1047,12 +1087,22 @@ implementation
begin
fromsubsetregdef:=tcgsize2orddef(fromsreg.subsetregsize);
tosubsetregdef:=tcgsize2orddef(tosreg.subsetregsize);
- tmpreg:=getintregister(list,tosubsetregdef);
- a_load_reg_reg(list,fromsubsetregdef,tosubsetregdef,fromsreg.subsetreg,tmpreg);
if (fromsreg.startbit<=tosreg.startbit) then
- a_op_const_reg(list,OP_SHL,tosubsetregdef,tosreg.startbit-fromsreg.startbit,tmpreg)
+ begin
+ { tosreg may be larger -> use its size to perform the shift }
+ tmpreg:=getintregister(list,tosubsetregdef);
+ a_load_reg_reg(list,fromsubsetregdef,tosubsetregdef,fromsreg.subsetreg,tmpreg);
+ a_op_const_reg(list,OP_SHL,tosubsetregdef,tosreg.startbit-fromsreg.startbit,tmpreg)
+ end
else
- a_op_const_reg(list,OP_SHR,tosubsetregdef,fromsreg.startbit-tosreg.startbit,tmpreg);
+ begin
+ { fromsreg may be larger -> use its size to perform the shift }
+ tmpreg:=getintregister(list,fromsubsetregdef);
+ a_op_const_reg_reg(list,OP_SHR,fromsubsetregdef,fromsreg.startbit-tosreg.startbit,fromsreg.subsetreg,tmpreg);
+ tmpreg2:=getintregister(list,tosubsetregdef);
+ a_load_reg_reg(list,fromsubsetregdef,tosubsetregdef,tmpreg,tmpreg2);
+ tmpreg:=tmpreg2;
+ end;
stopbit:=tosreg.startbit + tosreg.bitlen;
// on x86(64), 1 shl 32(64) = 1 instead of 0
if (stopbit<>AIntBits) then
@@ -2724,6 +2774,235 @@ implementation
g_concatcopy(list,size,source,dest);
end;
+ procedure thlcgobj.g_copyshortstring(list: TAsmList; const source, dest: treference; strdef: tstringdef);
+ var
+ cgpara1,cgpara2,cgpara3 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ cgpara3.init;
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,s32inttype,cgpara3);
+ a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3);
+ a_loadaddr_ref_cgpara(list,strdef,source,cgpara2);
+ a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1);
+ paramanager.freecgpara(list,cgpara3);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara1);
+ g_call_system_proc(list,'fpc_shortstr_assign');
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+ procedure thlcgobj.g_copyvariant(list: TAsmList; const source, dest: treference; vardef: tvariantdef);
+ var
+ cgpara1,cgpara2 : TCGPara;
+ pvardata : tdef;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ pvardata:=getpointerdef(search_system_type('TVARDATA').typedef);
+ paramanager.getintparaloc(pocall_default,1,pvardata,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,pvardata,cgpara2);
+ a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2);
+ a_loadaddr_ref_cgpara(list,vardef,source,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara1);
+ g_call_system_proc(list,'fpc_variant_copy_overwrite');
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+ procedure thlcgobj.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,voidpointertype,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,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,t,ref,cgpara1)
+ else
+ { these functions get the pointer by value }
+ a_load_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ g_call_system_proc(list,incrfunc);
+ 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,voidpointertype,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ g_call_system_proc(list,'fpc_addref');
+ end;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+ procedure thlcgobj.g_initialize(list: TAsmList; t: tdef; const ref: treference);
+ var
+ href : treference;
+ cgpara1,cgpara2 : TCGPara;
+ pvardata : tdef;
+ 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,t,0,ref)
+ else if t.typ=variantdef then
+ begin
+ pvardata:=getpointerdef(search_system_type('TVARDATA').typedef);
+ paramanager.getintparaloc(pocall_default,1,pvardata,cgpara1);
+ a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ g_call_system_proc(list,'fpc_variant_init');
+ end
+ else
+ begin
+ if is_open_array(t) then
+ InternalError(201103052);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,cgpara2);
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
+ a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ g_call_system_proc(list,'fpc_initialize');
+ end;
+ cgpara1.done;
+ cgpara2.done;
+ end;
+
+ procedure thlcgobj.g_finalize(list: TAsmList; t: tdef; const ref: treference);
+ var
+ href : treference;
+ cgpara1,cgpara2 : TCGPara;
+ paratype : tdef;
+ decrfunc : string;
+ dynarr: boolean;
+ begin
+ paratype:=getpointerdef(voidpointertype);
+ 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
+ begin
+ paratype:=getpointerdef(search_system_type('TVARDATA').typedef);
+ decrfunc:='fpc_variant_clear'
+ end
+ else
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ if is_open_array(t) then
+ InternalError(201103051);
+ dynarr:=is_dynamic_array(t);
+ { fpc_finalize takes a pointer value parameter, fpc_dynarray_clear a
+ pointer var parameter }
+ if not dynarr then
+ paratype:=voidpointertype;
+ paramanager.getintparaloc(pocall_default,1,paratype,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,cgpara2);
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
+ a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ if dynarr then
+ g_call_system_proc(list,'fpc_dynarray_clear')
+ else
+ g_call_system_proc(list,'fpc_finalize');
+ cgpara1.done;
+ cgpara2.done;
+ exit;
+ end;
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,paratype,cgpara1);
+ a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ g_call_system_proc(list,decrfunc);
+ cgpara1.done;
+ end;
+
+ procedure thlcgobj.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,voidpointertype,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,ptrsinttype,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,ptrsinttype,highloc.value+1,cgpara3)
+ else
+ begin
+ if highloc.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ hreg:=highloc.register
+ else
+ begin
+ hreg:=getintregister(list,ptrsinttype);
+ a_load_loc_reg(list,ptrsinttype,ptrsinttype,highloc,hreg);
+ end;
+ { increment, converts high(x) to length(x) }
+ lenreg:=getintregister(list,ptrsinttype);
+ a_op_const_reg_reg(list,OP_ADD,ptrsinttype,1,hreg,lenreg);
+ a_load_reg_cgpara(list,ptrsinttype,lenreg,cgpara3);
+ end;
+
+ a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara3);
+ g_call_system_proc(list,name);
+
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
procedure thlcgobj.g_rangecheck(list: TAsmList; const l: tlocation; fromdef, todef: tdef);
var
{$if defined(cpu64bitalu) or defined(cpu32bitalu)}
@@ -3201,6 +3480,13 @@ implementation
current_filepos:=storepos;
end;
+
+ function use_ent : boolean;
+ begin
+ use_ent := (target_info.system in [system_mipsel_linux,system_mipseb_linux])
+ or (target_info.cpu=cpu_alpha);
+ end;
+
procedure thlcgobj.gen_proc_symbol(list: TAsmList);
var
item,
@@ -3234,11 +3520,15 @@ implementation
previtem:=item;
item := TCmdStrListItem(item.next);
end;
+ if (use_ent) then
+ list.concat(Tai_ent.create(current_procinfo.procdef.mangledname));
current_procinfo.procdef.procstarttai:=tai(list.last);
end;
procedure thlcgobj.gen_proc_symbol_end(list: TAsmList);
begin
+ if (use_ent) then
+ list.concat(Tai_ent_end.create(current_procinfo.procdef.mangledname));
list.concat(Tai_symbol_end.Createname(current_procinfo.procdef.mangledname));
current_procinfo.procdef.procendtai:=tai(list.last);
@@ -3600,7 +3890,7 @@ implementation
else
highloc.loc:=LOC_INVALID;
eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
- g_array_rtti_helper(list,eldef,href,highloc,'FPC_FINALIZE_ARRAY');
+ g_array_rtti_helper(list,eldef,href,highloc,'fpc_finalize_array');
end
else
g_finalize(list,tparavarsym(p).vardef,href);
@@ -3663,7 +3953,7 @@ implementation
{ open arrays do not contain correct element count in their rtti,
the actual count must be passed separately. }
eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
- g_array_rtti_helper(list,eldef,href,highloc,'FPC_ADDREF_ARRAY');
+ g_array_rtti_helper(list,eldef,href,highloc,'fpc_addref_array');
end
else
g_incrrefcount(list,tparavarsym(p).vardef,href);
@@ -3691,7 +3981,7 @@ implementation
else
highloc.loc:=LOC_INVALID;
eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
- g_array_rtti_helper(list,eldef,href,highloc,'FPC_INITIALIZE_ARRAY');
+ g_array_rtti_helper(list,eldef,href,highloc,'fpc_initialize_array');
end
else
g_initialize(list,tparavarsym(p).vardef,href);
@@ -4022,7 +4312,9 @@ implementation
(srsym.typ<>procsym) then
Message1(cg_f_unknown_compilerproc,procname);
pd:=tprocdef(tprocsym(srsym).procdeflist[0]);
+ allocallcpuregisters(list);
a_call_name(list,pd,pd.mangledname,false);
+ deallocallcpuregisters(list);
end;
diff --git a/mips/compiler/htypechk.pas b/mips/compiler/htypechk.pas
index a62fff5d57..13f6875242 100644
--- a/mips/compiler/htypechk.pas
+++ b/mips/compiler/htypechk.pas
@@ -2417,7 +2417,9 @@ implementation
(
(count=1) or
equal_defs(tprocvardef(currpt.left.resultdef).returndef,def_to)
- ) then
+ ) and
+ { and if it doesn't require any parameters }
+ (tprocvardef(currpt.left.resultdef).minparacount=0) then
begin
releasecurrpt:=true;
currpt:=tcallparanode(pt.getcopy);
diff --git a/mips/compiler/i386/cpupara.pas b/mips/compiler/i386/cpupara.pas
index 0755adabf8..6c904cf451 100644
--- a/mips/compiler/i386/cpupara.pas
+++ b/mips/compiler/i386/cpupara.pas
@@ -45,7 +45,7 @@ unit cpupara;
and if the calling conventions for the helper routines of the
rtl are used.
}
- procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -270,14 +270,15 @@ unit cpupara;
end;
- procedure ti386paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ procedure ti386paramanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
begin
cgpara.reset;
- cgpara.size:=OS_ADDR;
- cgpara.intsize:=sizeof(pint);
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(calloption);
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -321,18 +322,6 @@ unit cpupara;
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
@@ -342,37 +331,23 @@ unit cpupara;
(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
+
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
+
+ { 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
- paraloc:=result.add_location;
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.size:=retcgsize;
- exit;
+ result.def:=sinttype;
+ result.intsize:=sizeof(aint);
+ retcgsize:=OS_SINT;
+ result.size:=retcgsize;
end;
+
{ Return in FPU register? }
if def.typ=floatdef then
begin
@@ -420,6 +395,7 @@ unit cpupara;
var
i : integer;
hp : tparavarsym;
+ paradef : tdef;
paraloc : pcgparalocation;
l,
paralen,
@@ -451,15 +427,17 @@ unit cpupara;
(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);
+ paradef:=hp.vardef;
+ pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
if pushaddr then
begin
paralen:=sizeof(aint);
paracgsize:=OS_ADDR;
+ paradef:=getpointerdef(paradef);
end
else
begin
- paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+ paralen:=push_size(hp.varspez,paradef,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
@@ -467,15 +445,17 @@ unit cpupara;
(paralen > 0) and
(paralen < sizeof(aint)) then
begin
- paralen := sizeof(aint);
+ paralen:=sizeof(aint);
paracgsize:=OS_SINT;
+ paradef:=sinttype;
end
else
- paracgsize:=def_cgsize(hp.vardef);
+ paracgsize:=def_cgsize(paradef);
end;
hp.paraloc[side].reset;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
hp.paraloc[side].Alignment:=paraalign;
{ Copy to stack? }
if (paracgsize=OS_NO) or
@@ -553,6 +533,7 @@ unit cpupara;
var parareg,parasize:longint);
var
hp : tparavarsym;
+ paradef : tdef;
paraloc : pcgparalocation;
paracgsize : tcgsize;
i : integer;
@@ -585,14 +566,15 @@ unit cpupara;
while true do
begin
hp:=tparavarsym(paras[i]);
+ paradef:=hp.vardef;
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;
+ paradef:=getpointerdef(paradef);
end
else
begin
@@ -602,6 +584,7 @@ unit cpupara;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen;
hp.paraloc[side].Alignment:=paraalign;
+ hp.paraloc[side].def:=paradef;
{
EAX
EDX
diff --git a/mips/compiler/jvm/cpubase.pas b/mips/compiler/jvm/cpubase.pas
index 57e6c46298..ee82ea3ede 100644
--- a/mips/compiler/jvm/cpubase.pas
+++ b/mips/compiler/jvm/cpubase.pas
@@ -254,7 +254,7 @@ uses
);
{ this is only for the generic code which is not used for this architecture }
- saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
{# Required parameter alignment when calling a routine
}
diff --git a/mips/compiler/jvm/cpupara.pas b/mips/compiler/jvm/cpupara.pas
index 2a63551489..761581f8f6 100644
--- a/mips/compiler/jvm/cpupara.pas
+++ b/mips/compiler/jvm/cpupara.pas
@@ -42,7 +42,7 @@ interface
{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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -64,9 +64,9 @@ implementation
hlcgobj;
- procedure TJVMParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
+ procedure TJVMParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
begin
- { don't know whether it's an actual integer or a pointer (necessary for cgpara.def) }
+ { not yet implemented/used }
internalerror(2010121001);
end;
diff --git a/mips/compiler/jvm/hlcgcpu.pas b/mips/compiler/jvm/hlcgcpu.pas
index 92f3d2ec56..7e317ae5bc 100644
--- a/mips/compiler/jvm/hlcgcpu.pas
+++ b/mips/compiler/jvm/hlcgcpu.pas
@@ -1527,7 +1527,7 @@ implementation
eleref: treference;
begin
{ only in case of initialisation, we have to set all elements to "empty" }
- if name<>'FPC_INITIALIZE_ARRAY' then
+ if name<>'fpc_initialize_array' then
exit;
{ put array on the stack }
a_load_ref_stack(list,java_jlobject,ref,prepare_stack_for_ref(list,ref,false));
@@ -1583,7 +1583,7 @@ implementation
not is_dynamic_array(t) then
begin
dummyloc.loc:=LOC_INVALID;
- g_array_rtti_helper(list,tarraydef(t).elementdef,ref,dummyloc,'FPC_INITIALIZE_ARRAY')
+ g_array_rtti_helper(list,tarraydef(t).elementdef,ref,dummyloc,'fpc_initialize_array')
end
else if is_record(t) then
begin
@@ -2128,6 +2128,9 @@ implementation
enum instance for 0 if it exists (if not, it remains nil since
there is no valid enum value in it) }
else if (vs.vardef.typ=enumdef) and
+ ((vs.typ<>fieldvarsym) or
+ (tdef(vs.owner.defowner).typ<>objectdef) or
+ (ts_jvm_enum_field_init in current_settings.targetswitches)) and
get_enum_init_val_ref(vs.vardef,initref) then
allocate_enum_with_base_ref(list,vs,initref,ref);
end;
diff --git a/mips/compiler/jvm/njvmld.pas b/mips/compiler/jvm/njvmld.pas
index 9c6c7b6fb0..8008b0ff0f 100644
--- a/mips/compiler/jvm/njvmld.pas
+++ b/mips/compiler/jvm/njvmld.pas
@@ -106,9 +106,12 @@ function tjvmassignmentnode.pass_1: tnode;
is_ansistring(tvecnode(target).left.resultdef)) then
begin
{ prevent errors in case of an expression such as
- word(str[x]):=1234;
+ word(unicodestr[x]):=1234;
}
- inserttypeconv_explicit(right,cwidechartype);
+ if is_wide_or_unicode_string(tvecnode(target).left.resultdef) then
+ inserttypeconv_explicit(right,cwidechartype)
+ else
+ inserttypeconv_explicit(right,cansichartype);
result:=ccallnode.createintern('fpc_'+tstringdef(tvecnode(target).left.resultdef).stringtypname+'_setchar',
ccallparanode.create(right,
ccallparanode.create(tvecnode(target).right,
diff --git a/mips/compiler/link.pas b/mips/compiler/link.pas
index bb3acd9d94..f45302de04 100644
--- a/mips/compiler/link.pas
+++ b/mips/compiler/link.pas
@@ -115,7 +115,8 @@ interface
property StaticLibraryList:TFPHashObjectList read FStaticLibraryList;
property ImportLibraryList:TFPHashObjectList read FImportLibraryList;
procedure DefaultLinkScript;virtual;abstract;
- procedure ConcatGenericSections(secnames:string);
+ procedure ScriptAddGenericSections(secnames:string);
+ procedure ScriptAddSourceStatements(AddSharedAsStatic:boolean);virtual;
public
IsSharedLibrary : boolean;
UseStabs : boolean;
@@ -531,15 +532,11 @@ Implementation
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;
@@ -901,6 +898,35 @@ Implementation
end;
+ procedure TInternalLinker.ScriptAddSourceStatements(AddSharedAsStatic:boolean);
+ var
+ s,s2: TCmdStr;
+ begin
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkScript.Concat('READOBJECT '+MaybeQuoted(s));
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ s:=StaticLibFiles.GetFirst;
+ if s<>'' then
+ LinkScript.Concat('READSTATICLIBRARY '+MaybeQuoted(s));
+ end;
+ if not AddSharedAsStatic then
+ exit;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
+ LinkScript.Concat('READSTATICLIBRARY '+MaybeQuoted(s2))
+ else
+ Comment(V_Error,'Import library not found for '+S);
+ end;
+ end;
+
+
procedure TInternalLinker.Load_ReadObject(const para:TCmdStr);
var
objdata : TObjData;
@@ -951,7 +977,10 @@ Implementation
inc(i);
s:=hp.str;
if (s='') or (s[1]='#') then
- continue;
+ begin
+ hp:=TCmdStrListItem(hp.next);
+ continue;
+ end;
keyword:=Upper(GetToken(s,' '));
para:=GetToken(s,' ');
if Trim(s)<>'' then
@@ -1037,6 +1066,7 @@ Implementation
if (s='') or (s[1]='#') then
begin
IsHandled^[i]:=true;
+ hp:=TCmdStrListItem(hp.next);
continue;
end;
handled:=true;
@@ -1084,7 +1114,10 @@ Implementation
inc(i);
s:=hp.str;
if (s='') or (s[1]='#') then
- continue;
+ begin
+ hp:=TCmdStrListItem(hp.next);
+ continue;
+ end;
handled:=true;
keyword:=Upper(GetToken(s,' '));
para:=ParsePara(GetToken(s,' '));
@@ -1136,7 +1169,10 @@ Implementation
inc(i);
s:=hp.str;
if (s='') or (s[1]='#') then
- continue;
+ begin
+ hp:=TCmdStrListItem(hp.next);
+ continue;
+ end;
handled:=true;
keyword:=Upper(GetToken(s,' '));
para:=ParsePara(GetToken(s,' '));
@@ -1172,7 +1208,10 @@ Implementation
inc(i);
s:=hp.str;
if (s='') or (s[1]='#') then
- continue;
+ begin
+ hp:=TCmdStrListItem(hp.next);
+ continue;
+ end;
handled:=true;
keyword:=Upper(GetToken(s,' '));
para:=ParsePara(GetToken(s,' '));
@@ -1261,6 +1300,7 @@ Implementation
{ Calc positions in mem }
ParseScript_MemPos;
exeoutput.FixupRelocations;
+ exeoutput.RemoveUnusedExeSymbols;
exeoutput.PrintMemoryMap;
if ErrorCount>0 then
goto myexit;
@@ -1335,7 +1375,7 @@ Implementation
end;
- procedure TInternalLinker.ConcatGenericSections(secnames:string);
+ procedure TInternalLinker.ScriptAddGenericSections(secnames:string);
var
secname:string;
begin
diff --git a/mips/compiler/m68k/cpubase.pas b/mips/compiler/m68k/cpubase.pas
index 42979a5dc5..9e8e140d6a 100644
--- a/mips/compiler/m68k/cpubase.pas
+++ b/mips/compiler/m68k/cpubase.pas
@@ -304,7 +304,7 @@ unit cpubase;
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);
+ 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
diff --git a/mips/compiler/m68k/cpupara.pas b/mips/compiler/m68k/cpupara.pas
index bf23642a98..1ee1863d55 100644
--- a/mips/compiler/m68k/cpupara.pas
+++ b/mips/compiler/m68k/cpupara.pas
@@ -41,7 +41,7 @@ unit cpupara;
rtl are used.
}
tm68kparamanager = class(tparamanager)
- procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -65,15 +65,17 @@ unit cpupara;
cpuinfo,cgutils,
defutil;
- procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);
+ procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
begin
if nr<1 then
internalerror(2002070801);
cgpara.reset;
- cgpara.size:=OS_INT;
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -196,38 +198,8 @@ unit cpupara;
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;
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
paraloc:=result.add_location;
{ Return in FPU register? }
@@ -334,15 +306,12 @@ unit cpupara;
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
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
{$ifdef DEBUG_CHARLIE}
writeln('loc register');
{$endif DEBUG_CHARLIE}
- paradef:=voidpointertype;
+ paradef:=getpointerdef(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@@ -367,6 +336,7 @@ unit cpupara;
hp.paraloc[side].alignment:=std_param_align;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
if (paralen = 0) then
if (paradef.typ = recorddef) then
diff --git a/mips/compiler/m68k/ra68kmot.pas b/mips/compiler/m68k/ra68kmot.pas
index b61ecbe50b..d2258bcce6 100644
--- a/mips/compiler/m68k/ra68kmot.pas
+++ b/mips/compiler/m68k/ra68kmot.pas
@@ -99,7 +99,7 @@ Implementation
systems,
{ aasm }
cpuinfo,aasmtai,aasmdata,aasmcpu,
- cgbase,
+ cgbase,cgutils,
{ symtable }
symbase,symtype,symsym,symdef,symtable,
{ pass 1 }
diff --git a/mips/compiler/mips/aasmcpu.pas b/mips/compiler/mips/aasmcpu.pas
index 065e23d67f..4493fb5abd 100644
--- a/mips/compiler/mips/aasmcpu.pas
+++ b/mips/compiler/mips/aasmcpu.pas
@@ -28,7 +28,7 @@ interface
uses
cclasses,
globtype, globals, verbose,
- aasmbase, aasmsym, aasmtai,
+ aasmbase, aasmdata, aasmsym, aasmtai,
cgbase, cgutils, cpubase, cpuinfo;
const
@@ -78,11 +78,16 @@ type
procedure InitAsm;
procedure DoneAsm;
+ procedure fixup_jmps(list: TAsmList);
+
function spilling_create_load(const ref: treference; r: tregister): taicpu;
function spilling_create_store(r: tregister; const ref: treference): taicpu;
implementation
+ uses
+ cutils;
+
{*****************************************************************************
taicpu Constructors
*****************************************************************************}
@@ -452,6 +457,146 @@ procedure DoneAsm;
end;
+procedure fixup_jmps(list: TAsmList);
+ var
+ p,pdelayslot: tai;
+ newcomment: tai_comment;
+ newjmp,newnoop: taicpu;
+ labelpositions: TFPList;
+ instrpos: ptrint;
+ l: tasmlabel;
+ inserted_something: boolean;
+ begin
+ // if certainly not enough instructions to cause an overflow, dont 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:
+ { probleim here: pseudo-instructions can translate into
+ several CPU instructions, possibly depending on assembler options,
+ to obe on safe side, let's assume a mean of two. }
+ inc(instrpos,2);
+ ait_const:
+ begin
+ if (tai_const(p).consttype<>aitconst_32bit) then
+ internalerror(2008052101);
+ inc(instrpos);
+ end;
+ end;
+ p := tai(p.next);
+ end;
+
+ { If the number of instructions is below limit, we can't overflow either }
+ if (instrpos <= (high(smallint) div 4)) then
+ exit;
+ // 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,2);
+ case taicpu(p).opcode of
+ A_BA:
+ 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
+ { This is not PIC safe }
+ taicpu(p).opcode:=A_J;
+ newcomment:=tai_comment.create(strpnew('fixup_jmps, A_BA changed into A_J'));
+ list.insertbefore(newcomment,p);
+ end;
+ A_BC:
+ if (taicpu(p).ops=3) and (taicpu(p).oper[2]^.typ = top_ref) and
+ assigned(taicpu(p).oper[2]^.ref^.symbol) and
+ (taicpu(p).oper[2]^.ref^.symbol is tasmlabel) and
+ (labelpositions[tasmlabel(taicpu(p).oper[2]^.ref^.symbol).labelnr] <> NIL) and
+{$push}
+{$q-}
+ (ptruint(abs(ptrint(labelpositions[tasmlabel(taicpu(p).oper[2]^.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 }
+ { plus delay slot }
+ { the current jump -> instrpos+3 }
+ labelpositions[l.labelnr] := pointer(instrpos+2*3);
+ pdelayslot:=tai(p.next);
+ { We need to insert the new instruction after the delay slot instruction ! }
+ while assigned(pdelayslot) and (pdelayslot.typ<>ait_instruction) do
+ pdelayslot:=tai(pdelayslot.next);
+
+ list.insertafter(tai_label.create(l),pdelayslot);
+ // add a new unconditional jump between this jump and the label
+ newcomment:=tai_comment.create(strpnew('fixup_jmps, A_BXX changed into A_BNOTXX label;A_J;label:'));
+ list.insertbefore(newcomment,p);
+ newjmp := taicpu.op_sym(A_J,taicpu(p).oper[2]^.ref^.symbol);
+ newjmp.is_jmp := true;
+ newjmp.fileinfo := taicpu(p).fileinfo;
+ list.insertafter(newjmp,pdelayslot);
+ inc(instrpos,2);
+ { Add a delay slot for new A_J instruction }
+ newnoop:=taicpu.op_none(A_NOP);
+ newnoop.fileinfo := taicpu(p).fileinfo;
+ list.insertafter(newnoop,newjmp);
+ inc(instrpos,2);
+ // change the conditional jump to point to the newly inserted label
+ tasmlabel(taicpu(p).oper[2]^.ref^.symbol).decrefs;
+ taicpu(p).oper[2]^.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_cpu := taicpu;
cai_align := tai_align;
diff --git a/mips/compiler/mips/cgcpu.pas b/mips/compiler/mips/cgcpu.pas
index d7e670236e..0482469d88 100644
--- a/mips/compiler/mips/cgcpu.pas
+++ b/mips/compiler/mips/cgcpu.pas
@@ -27,7 +27,7 @@ interface
uses
globtype, parabase,
- cgbase, cgutils, cgobj, cg64f32,
+ cgbase, cgutils, cgobj, cg64f32, cpupara,
aasmbase, aasmtai, aasmcpu, aasmdata,
cpubase, cpuinfo,
node, symconst, SymType, symdef,
@@ -36,6 +36,7 @@ uses
type
TCGMIPS = class(tcg)
public
+
procedure init_register_allocators; override;
procedure done_register_allocators; override;
function getfpuregister(list: tasmlist; size: Tcgsize): Tregister; override;
@@ -51,7 +52,6 @@ type
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;
@@ -508,21 +508,22 @@ procedure TCGMIPS.init_register_allocators;
begin
inherited init_register_allocators;
- if (cs_create_pic in current_settings.moduleswitches) and
+ { Keep RS_R25, i.e. $t9 for PIC call }
+ if (cs_create_pic in current_settings.moduleswitches) and assigned(current_procinfo) 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_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,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_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
first_int_imreg, []);
end
else
rg[R_INTREGISTER] := trgcpu.Create(R_INTREGISTER, R_SUBD,
[RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,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_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
first_int_imreg, []);
{
@@ -596,21 +597,21 @@ begin
href := r;
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_FPUREGISTER,LOC_CFPUREGISTER :
- a_loadfpu_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;
+ 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_FPUREGISTER,LOC_CFPUREGISTER :
+ a_loadfpu_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;
+ end;
Inc(href.offset, tcgsize2size[hloc^.size]);
hloc := hloc^.Next;
end;
@@ -686,8 +687,18 @@ end;
procedure TCGMIPS.a_call_name(list: tasmlist; const s: string; weak: boolean);
+var
+ href: treference;
begin
- list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s)));
+ if (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ reference_reset(href,sizeof(aint));
+ href.symbol:=current_asmdata.RefAsmSymbol(s);
+ a_loadaddr_ref_reg(list,href,NR_PIC_FUNC);
+ list.concat(taicpu.op_reg(A_JALR,NR_PIC_FUNC));
+ end
+ else
+ list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s)));
{ Delay slot }
list.concat(taicpu.op_none(A_NOP));
end;
@@ -695,6 +706,9 @@ end;
procedure TCGMIPS.a_call_reg(list: tasmlist; Reg: TRegister);
begin
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (Reg <> NR_PIC_FUNC) then
+ list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_PIC_FUNC));
list.concat(taicpu.op_reg(A_JALR, reg));
{ Delay slot }
list.concat(taicpu.op_none(A_NOP));
@@ -792,7 +806,7 @@ var
begin
if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
(
- (tcgsize2size[tosize] = tcgsize2size[fromsize]) and (tosize <> fromsize)
+ (tcgsize2size[tosize] = tcgsize2size[fromsize]) and (tosize <> fromsize)
) or ((fromsize = OS_S8) and
(tosize = OS_16)) then
begin
@@ -851,7 +865,8 @@ begin
if (href.base = NR_NO) and (href.index <> NR_NO) then
internalerror(200306171);
- if (cs_create_pic in current_settings.moduleswitches) and
+ if ((cs_create_pic in current_settings.moduleswitches) or
+ (ref.refaddr=addr_pic)) and
assigned(href.symbol) then
begin
tmpreg := r; //GetIntRegister(list, OS_ADDR);
@@ -861,6 +876,11 @@ begin
tmpref.refaddr := addr_pic;
if not (pi_needs_got in current_procinfo.flags) then
internalerror(200501161);
+ if current_procinfo.got=NR_NO then
+ current_procinfo.got:=NR_GP;
+ { for addr_pic NR_GP can be implicit or explicit }
+ if (href.refaddr=addr_pic) and (href.base=current_procinfo.got) then
+ href.base:=NR_NO;
tmpref.base := current_procinfo.got;
list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
href.symbol := nil;
@@ -876,6 +896,8 @@ begin
else
href.base := tmpreg;
end;
+ if (href.base=NR_NO) and (href.offset=0) then
+ exit;
end;
@@ -941,18 +963,19 @@ end;
procedure TCGMIPS.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);
+ FpuMovInstr: array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
+ ((A_MOV_S, A_CVT_D_S),(A_CVT_S_D,A_MOV_D));
var
instr: taicpu;
begin
- if reg1 <> reg2 then
+ if (reg1 <> reg2) or (fromsize<>tosize) then
begin
- instr := taicpu.op_reg_reg(fpumovinstr[tosize], reg2, reg1);
+ instr := taicpu.op_reg_reg(fpumovinstr[fromsize,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);
+ if (fromsize=tosize) then
+ add_move_instruction(instr);
end;
end;
@@ -962,7 +985,7 @@ var
tmpref: treference;
tmpreg: tregister;
begin
- case tosize of
+ case fromsize of
OS_F32:
handle_load_store_fpu(list, False, A_LWC1, reg, ref);
OS_F64:
@@ -970,6 +993,8 @@ begin
else
InternalError(2007042701);
end;
+ if tosize<>fromsize then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
end;
procedure TCGMIPS.a_loadfpu_reg_ref(list: tasmlist; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference);
@@ -977,6 +1002,8 @@ var
tmpref: treference;
tmpreg: tregister;
begin
+ if tosize<>fromsize then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
case tosize of
OS_F32:
handle_load_store_fpu(list, True, A_SWC1, reg, ref);
@@ -1057,7 +1084,8 @@ var
begin
case Op of
OP_NEG:
- list.concat(taicpu.op_reg_reg(A_NEG, dst, src));
+ { discard overflow checking }
+ list.concat(taicpu.op_reg_reg(A_NEGU{A_NEG}, dst, src));
OP_NOT:
begin
list.concat(taicpu.op_reg_reg(A_NOT, dst, src));
@@ -1275,6 +1303,7 @@ end;
ai := taicpu.op_reg_reg_sym(A_BC, reg, tmpreg, l);
ai.SetCondition(TOpCmp2AsmCond[cmp_op]);
list.concat(ai);
+ { Delay slot }
list.Concat(TAiCpu.Op_none(A_NOP));
end;
@@ -1286,6 +1315,7 @@ begin
ai := taicpu.op_reg_reg_sym(A_BC, reg2, reg1, l);
ai.SetCondition(TOpCmp2AsmCond[cmp_op]);
list.concat(ai);
+ { Delay slot }
list.Concat(TAiCpu.Op_none(A_NOP));
end;
@@ -1296,6 +1326,7 @@ var
begin
ai := taicpu.op_sym(A_BA, l);
list.concat(ai);
+ { Delay slot }
list.Concat(TAiCpu.Op_none(A_NOP));
end;
@@ -1332,17 +1363,21 @@ procedure TCGMIPS.g_proc_entry(list: tasmlist; localsize: longint; nostackframe:
var
lastintoffset,lastfpuoffset,
nextoffset : aint;
+ i : longint;
+ ra_save,framesave,gp_save : taicpu;
fmask,mask : dword;
saveregs : tcpuregisterset;
+ StoreOp : TAsmOp;
href: treference;
usesfpr, usesgpr, gotgot : boolean;
reg : Tsuperregister;
helplist : TAsmList;
begin
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+
if nostackframe then
exit;
- a_reg_alloc(list,NR_STACK_POINTER_REG);
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
a_reg_alloc(list,NR_FRAME_POINTER_REG);
@@ -1356,24 +1391,19 @@ begin
fmask:=0;
nextoffset:=TMIPSProcInfo(current_procinfo).floatregstart;
lastfpuoffset:=LocalSize;
- { not sure about how used_in_proc is set, to play safe, we check the even register and save pair if used }
- reg := RS_F0;
- while reg < RS_F31 do
+ for reg := RS_F0 to RS_F30 do { to check: what if F30 is double? }
begin
if reg in (rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall)) then
begin
usesfpr:=true;
- fmask:=fmask or (3 shl ord(reg));
+ fmask:=fmask or (1 shl ord(reg));
href.offset:=nextoffset;
lastfpuoffset:=nextoffset;
+ if cs_asm_source in current_settings.globalswitches then
+ helplist.concat(tai_comment.Create(strpnew(std_regname(newreg(R_FPUREGISTER,reg,R_SUBFS))+' register saved.')));
helplist.concat(taicpu.op_reg_ref(A_SWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
inc(nextoffset,4);
- href.offset:=nextoffset;
- lastfpuoffset:=nextoffset;
- helplist.concat(taicpu.op_reg_ref(A_SWC1,newreg(R_FPUREGISTER,reg+1,R_SUBFS),href));
- inc(nextoffset,4);
end;
- reg := reg + 2;
end;
usesgpr:=false;
@@ -1381,7 +1411,15 @@ begin
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
include(saveregs,RS_R31);
+ if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
+ include(saveregs,RS_FRAME_POINTER_REG);
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ include(saveregs,RS_GP);
lastintoffset:=LocalSize;
+ framesave:=nil;
+ gp_save:=nil;
+
for reg:=RS_R1 to RS_R31 do
begin
if reg in saveregs then
@@ -1390,35 +1428,161 @@ begin
mask:=mask or (1 shl ord(reg));
href.offset:=nextoffset;
lastintoffset:=nextoffset;
- helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
+ if (reg=RS_FRAME_POINTER_REG) then
+ framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
+ else if (reg=RS_R31) then
+ ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
+ else if (reg=RS_GP) and
+ (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ gp_save:=taicpu.op_const(A_P_CPRESTORE,nextoffset)
+ else
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ helplist.concat(tai_comment.Create(strpnew(
+ std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))+' register saved.')));
+ helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
+ end;
inc(nextoffset,4);
end;
end;
+ //list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG,current_procinfo.para_stack_size));
list.concat(Taicpu.op_none(A_P_SET_NOMIPS16));
list.concat(Taicpu.op_reg_const_reg(A_P_FRAME,current_procinfo.framepointer,LocalSize,NR_R31));
list.concat(Taicpu.op_const_const(A_P_MASK,mask,-(LocalSize-lastintoffset)));
list.concat(Taicpu.op_const_const(A_P_FMASK,Fmask,-(LocalSize-lastfpuoffset)));
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ list.concat(Taicpu.op_reg(A_P_CPLOAD,NR_PIC_FUNC));
+ end;
list.concat(Taicpu.op_none(A_P_SET_NOREORDER));
- list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
- if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
- list.concat(Taicpu.Op_reg_reg(A_MOVE,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG));
-
if (-LocalSize >= simm16lo) and (-LocalSize <= simm16hi) then
- list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-LocalSize))
+ begin
+ list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
+ if cs_asm_source in current_settings.globalswitches then
+ begin
+ list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size')));
+ list.concat(tai_comment.Create(strpnew(' 0-'+
+ tostr(TMIPSProcInfo(current_procinfo).maxpushedparasize)+' for called function parameters')));
+ list.concat(tai_comment.Create(strpnew('Register save area at '+
+ tostr(TMIPSProcInfo(current_procinfo).intregstart))));
+ list.concat(tai_comment.Create(strpnew('FPU register save area at '+
+ tostr(TMIPSProcInfo(current_procinfo).floatregstart))));
+ end;
+ list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-LocalSize));
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('RA register saved.')));
+ list.concat(ra_save);
+ if assigned(framesave) then
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('Frame S8/FP register saved.')));
+ list.concat(framesave);
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('New frame FP register set to $sp+'+ToStr(LocalSize))));
+ list.concat(Taicpu.op_reg_reg_const(A_ADDIU,NR_FRAME_POINTER_REG,
+ NR_STACK_POINTER_REG,LocalSize));
+ end;
+ end
else
begin
- list.concat(Taicpu.Op_reg_const(A_LI,NR_R1,-LocalSize));
- list.concat(Taicpu.Op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R1));
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size using R9/t1 register')));
+ list.concat(Taicpu.Op_reg_const(A_LI,NR_R9,-LocalSize));
+ list.concat(Taicpu.Op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R9));
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('RA register saved.')));
+ list.concat(ra_save);
+ if assigned(framesave) then
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('Frame register saved.')));
+ list.concat(framesave);
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('Frame register updated to $SP+R9 value')));
+ list.concat(Taicpu.op_reg_reg_reg(A_SUBU,NR_FRAME_POINTER_REG,
+ NR_STACK_POINTER_REG,NR_R9));
+ end;
+ { The instructions before are macros that can extend to multiple instructions,
+ the settings of R9 to -LocalSize surely does,
+ but the saving of RA and FP also might, and might
+ even use AT register, which is why we use R9 instead of AT here for -LocalSize }
+ list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
+ end;
+ if assigned(gp_save) then
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('GOT register saved.')));
+ list.concat(Taicpu.op_none(A_P_SET_MACRO));
+ list.concat(gp_save);
+ list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
+ end;
+
+ with TMIPSProcInfo(current_procinfo) do
+ begin
+ href.offset:=0;
+ //if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ href.base:=NR_FRAME_POINTER_REG;
+
+ for i:=0 to MIPS_MAX_REGISTERS_USED_IN_CALL-1 do
+ if (register_used[i]) then
+ begin
+ reg:=parasupregs[i];
+ if register_offset[i]=-1 then
+ comment(V_warning,'Register parameter has offset -1 in TCGMIPS.g_proc_entry');
+
+ //if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ // href.offset:=register_offset[i]+Localsize
+ //else
+ href.offset:=register_offset[i];
+{$ifdef MIPSEL}
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('Var '+
+ register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
+ +' saved to offset '+tostr(href.offset))));
+ list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
+{$else not MIPSEL, for big endian, size matters}
+ case register_size[i] of
+ OS_8,
+ OS_S8:
+ StoreOp := A_SB;
+ OS_16,
+ OS_S16:
+ StoreOp := A_SH;
+ OS_32,
+ OS_NO,
+ OS_F32,
+ OS_S32:
+ StoreOp := A_SW;
+ OS_F64,
+ OS_64,
+ OS_S64:
+ begin
+{$ifdef cpu64bitalu}
+ StoreOp:=A_SD;
+{$else not cpu64bitalu}
+ StoreOp:= A_SW;
+{$endif not cpu64bitalu}
+ end
+ else
+ internalerror(2012061801);
+ end;
+ if cs_asm_source in current_settings.globalswitches then
+ list.concat(tai_comment.Create(strpnew('Var '+
+ register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
+ +' saved to offset '+tostr(href.offset))));
+ list.concat(taicpu.op_reg_ref(StoreOp, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
+{$endif}
+ end;
end;
-
if (cs_create_pic in current_settings.moduleswitches) and
- (pi_needs_got in current_procinfo.flags) then
+ (pi_needs_got in current_procinfo.flags) then
begin
current_procinfo.got := NR_GP;
end;
-
list.concatList(helplist);
helplist.Free;
end;
@@ -1446,24 +1610,21 @@ begin
href.base:=NR_STACK_POINTER_REG;
nextoffset:=TMIPSProcInfo(current_procinfo).floatregstart;
- reg := RS_F0;
- while reg < RS_F31 do
- begin
- if reg in (rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall)) then
- begin
- href.offset:=nextoffset;
- list.concat(taicpu.op_reg_ref(A_LWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
- inc(nextoffset,4);
- href.offset:=nextoffset;
- list.concat(taicpu.op_reg_ref(A_LWC1,newreg(R_FPUREGISTER,reg+1,R_SUBFS),href));
- inc(nextoffset,4);
- end;
- reg := reg + 2;
- end;
+ for reg := RS_F0 to RS_F30 do
+ begin
+ if reg in (rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall)) then
+ begin
+ href.offset:=nextoffset;
+ list.concat(taicpu.op_reg_ref(A_LWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
+ inc(nextoffset,4);
+ end;
+ end;
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
include(saveregs,RS_R31);
+ if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
+ include(saveregs,RS_FRAME_POINTER_REG);
for reg:=RS_R1 to RS_R31 do
begin
if reg in saveregs then
@@ -1503,10 +1664,10 @@ 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);
+ paramanager.getintparaloc(pocall_default, 1, voidpointertype, paraloc1);
+ paramanager.getintparaloc(pocall_default, 2, voidpointertype, paraloc2);
+ paramanager.getintparaloc(pocall_default, 3, ptrsinttype, paraloc3);
+ a_load_const_cgpara(list, OS_SINT, len, paraloc3);
a_loadaddr_ref_cgpara(list, dest, paraloc2);
a_loadaddr_ref_cgpara(list, Source, paraloc1);
paramanager.freecgpara(list, paraloc3);
@@ -1677,25 +1838,30 @@ end;
procedure TCGMIPS.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint);
- procedure loadvmttor25;
+ procedure loadvmttorvmt;
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_R25);
+ cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_VMT);
end;
- procedure op_onr25methodaddr;
+ procedure op_onrvmtmethodaddr;
var
href : treference;
+ reg : tregister;
begin
if (procdef.extnumber=$ffff) then
Internalerror(200006139);
{ call/jmp vmtoffs(%eax) ; method offs }
- reference_reset_base(href, NR_R25, tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber), sizeof(aint));
- cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R25);
- list.concat(taicpu.op_reg(A_JR, NR_R25));
+ reference_reset_base(href, NR_VMT, tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber), sizeof(aint));
+ if (cs_create_pic in current_settings.moduleswitches) then
+ reg:=NR_PIC_FUNC
+ else
+ reg:=NR_VMT;
+ cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, reg);
+ list.concat(taicpu.op_reg(A_JR, reg));
end;
var
make_global: boolean;
@@ -1726,8 +1892,8 @@ begin
if (po_virtualmethod in procdef.procoptions) and
not is_objectpascal_helper(procdef.struct) then
begin
- loadvmttor25;
- op_onr25methodaddr;
+ loadvmttorvmt;
+ op_onrvmtmethodaddr;
end
else
list.concat(taicpu.op_sym(A_J,current_asmdata.RefAsmSymbol(procdef.mangledname)));
@@ -1755,8 +1921,15 @@ procedure TCGMIPS.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCG
procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference);
var
tmpref: treference;
+ tmpreg: tregister;
begin
{ Override this function to prevent loading the reference twice }
+ if target_info.endian = endian_big then
+ begin
+ tmpreg := reg.reglo;
+ reg.reglo := reg.reghi;
+ reg.reghi := tmpreg;
+ end;
tmpref := ref;
cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reglo, tmpref);
Inc(tmpref.offset, 4);
@@ -1767,8 +1940,15 @@ end;
procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64);
var
tmpref: treference;
+ tmpreg: tregister;
begin
{ Override this function to prevent loading the reference twice }
+ if target_info.endian = endian_big then
+ begin
+ tmpreg := reg.reglo;
+ reg.reglo := reg.reghi;
+ reg.reghi := tmpreg;
+ end;
tmpref := ref;
cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reglo);
Inc(tmpref.offset, 4);
diff --git a/mips/compiler/mips/cpubase.pas b/mips/compiler/mips/cpubase.pas
index f1dabbe0e9..54898b6c51 100644
--- a/mips/compiler/mips/cpubase.pas
+++ b/mips/compiler/mips/cpubase.pas
@@ -98,6 +98,9 @@ unit cpubase;
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;
@@ -130,17 +133,35 @@ unit cpubase;
const
max_operands = 4;
+
maxintregs = 31;
- maxfpuregs = 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
*****************************************************************************}
@@ -160,13 +181,22 @@ unit cpubase;
Generic Register names
*****************************************************************************}
+
+ { PIC Code }
NR_GP = NR_R28;
+ NR_PIC_FUNC = NR_R25;
+ RS_GP = RS_R28;
+ RS_PIC_FUNC = RS_R25;
+
+ { VMT code }
+ NR_VMT = NR_R24;
+ RS_VMT = RS_R24;
+
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;
@@ -223,7 +253,7 @@ unit cpubase;
(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);
+ 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
diff --git a/mips/compiler/mips/cpugas.pas b/mips/compiler/mips/cpugas.pas
index a3807882e4..1f36324508 100644
--- a/mips/compiler/mips/cpugas.pas
+++ b/mips/compiler/mips/cpugas.pas
@@ -31,6 +31,7 @@ unit cpugas;
type
TMIPSGNUAssembler = class(TGNUassembler)
+ nomacro, noreorder, noat : boolean;
constructor create(smart: boolean); override;
end;
@@ -38,12 +39,46 @@ unit cpugas;
procedure WriteInstruction(hp : tai);override;
end;
+ const
+ use_std_regnames : boolean =
+ {$ifndef USE_MIPS_GAS_REGS}
+ true;
+ {$else}
+ false;
+ {$endif}
+
implementation
uses
- cutils, systems,
+ aasmbase, cutils, systems,
verbose, itcpugas, cgbase, cgutils;
+ function gas_std_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;
+ result:=std_regname(hr);
+ end;
+
+
+ function asm_regname(reg : TRegister) : string;
+
+ begin
+ if use_std_regnames then
+ asm_regname:='$'+gas_std_regname(reg)
+ else
+ asm_regname:=gas_regname(reg);
+ end;
+
{****************************************************************************}
{ GNU MIPS Assembler writer }
{****************************************************************************}
@@ -52,6 +87,9 @@ unit cpugas;
begin
inherited create(smart);
InstrWriter := TMIPSInstrWriter.create(self);
+ nomacro:=false;
+ noreorder:=false;
+ noat:=false;
end;
@@ -60,14 +98,25 @@ unit cpugas;
{****************************************************************************}
function GetReferenceString(var ref: TReference): string;
+ var
+ hasgot : boolean;
+ gotprefix : string;
begin
GetReferenceString := '';
+ hasgot:=false;
with ref do
begin
if (base = NR_NO) and (index = NR_NO) then
begin
if assigned(symbol) then
- GetReferenceString := symbol.Name;
+ begin
+ GetReferenceString := symbol.Name;
+ if symbol.typ=AT_FUNCTION then
+ gotprefix:='%call16('
+ else
+ gotprefix:='%got(';
+ hasgot:=true;
+ end;
if offset > 0 then
GetReferenceString := GetReferenceString + '+' + ToStr(offset)
else if offset < 0 then
@@ -77,6 +126,13 @@ unit cpugas;
GetReferenceString := '%hi(' + GetReferenceString + ')';
addr_low:
GetReferenceString := '%lo(' + GetReferenceString + ')';
+ addr_pic:
+ begin
+ if hasgot then
+ GetReferenceString := gotprefix + GetReferenceString + ')'
+ else
+ internalerror(2012070401);
+ end;
end;
end
else
@@ -87,7 +143,7 @@ unit cpugas;
internalerror(2003052601);
{$endif extdebug}
if base <> NR_NO then
- GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
+ GetReferenceString := GetReferenceString + '(' + asm_regname(base) + ')';
if index = NR_NO then
begin
if offset <> 0 then
@@ -96,6 +152,14 @@ unit cpugas;
begin
if refaddr = addr_low then
GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
+ else if refaddr = addr_pic then
+ begin
+ if symbol.typ=AT_FUNCTION then
+ gotprefix:='%call16('
+ else
+ gotprefix:='%got(';
+ GetReferenceString := gotprefix + symbol.Name + ')' + GetReferenceString;
+ end
else
GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
end;
@@ -106,7 +170,7 @@ unit cpugas;
if (Offset<>0) or assigned(symbol) then
internalerror(2003052603);
{$endif extdebug}
- GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
+ GetReferenceString := GetReferenceString + '(' + asm_regname(index) + ')';
end;
end;
@@ -119,7 +183,7 @@ unit cpugas;
with Oper do
case typ of
top_reg:
- getopstr := gas_regname(reg);
+ getopstr := asm_regname(reg);
top_const:
getopstr := tostr(longint(val));
top_ref:
@@ -171,6 +235,11 @@ unit cpugas;
end;
}
+ function is_macro_instruction(op : TAsmOp) : boolean;
+ begin
+ is_macro_instruction :=
+ (op=A_SEQ) or (op=A_SNE);
+ end;
procedure TMIPSInstrWriter.WriteInstruction(hp: Tai);
var
@@ -201,21 +270,25 @@ unit cpugas;
begin
s := #9 + '.set' + #9 + 'macro';
owner.AsmWriteLn(s);
+ TMIPSGNUAssembler(owner).nomacro:=false;
end;
A_P_SET_REORDER:
begin
s := #9 + '.set' + #9 + 'reorder';
owner.AsmWriteLn(s);
+ TMIPSGNUAssembler(owner).noreorder:=false;
end;
A_P_SET_NOMACRO:
begin
s := #9 + '.set' + #9 + 'nomacro';
owner.AsmWriteLn(s);
+ TMIPSGNUAssembler(owner).nomacro:=true;
end;
A_P_SET_NOREORDER:
begin
s := #9 + '.set' + #9 + 'noreorder';
owner.AsmWriteLn(s);
+ TMIPSGNUAssembler(owner).noreorder:=true;
end;
A_P_SW:
begin
@@ -229,39 +302,57 @@ unit cpugas;
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);
+ if (target_info.endian = endian_big) then
+ begin
+ s := #9 + gas_op2str[A_LDC1] + #9 + getopstr(taicpu(hp).oper[0]^)
+ + ',' + getopstr(taicpu(hp).oper[1]^);
+ end
+ else
+ 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);
{ bug if $f9/$f19
tmpfpu_len := length(tmpfpu);
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
-
+
}
- r := taicpu(hp).oper[0]^.reg;
- setsupreg(r, getsupreg(r) + 1);
- tmpfpu := gas_regname(r);
- s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ r := taicpu(hp).oper[0]^.reg;
+ setsupreg(r, getsupreg(r) + 1);
+ tmpfpu := asm_regname(r);
+ s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ end;
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);
+ if (target_info.endian = endian_big) then
+ begin
+ s := #9 + gas_op2str[A_SDC1] + #9 + getopstr(taicpu(hp).oper[0]^)
+ + ',' + getopstr(taicpu(hp).oper[1]^);
+ end
+ else
+ 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]);
}
- r := taicpu(hp).oper[0]^.reg;
- setsupreg(r, getsupreg(r) + 1);
- tmpfpu := gas_regname(r);
- s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ r := taicpu(hp).oper[0]^.reg;
+ setsupreg(r, getsupreg(r) + 1);
+ tmpfpu := asm_regname(r);
+ s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ end;
owner.AsmWriteLn(s);
end;
else
begin
+ if is_macro_instruction(op) and TMIPSGNUAssembler(owner).nomacro then
+ owner.AsmWriteln(#9'.set'#9'macro');
s := #9 + gas_op2str[op] + cond2str[taicpu(hp).condition];
if taicpu(hp).delayslot_annulled then
s := s + ',a';
@@ -272,6 +363,8 @@ unit cpugas;
s := s + ',' + getopstr(taicpu(hp).oper[i]^);
end;
owner.AsmWriteLn(s);
+ if is_macro_instruction(op) and TMIPSGNUAssembler(owner).nomacro then
+ owner.AsmWriteln(#9'.set'#9'nomacro');
end;
end;
end;
@@ -283,19 +376,19 @@ unit cpugas;
id: as_gas;
idtxt: 'AS';
asmbin: 'as';
- asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
+ asmcmd: '-mips2 $NOWARN -EL $PIC -o $OBJ $ASM';
supported_targets: [system_mipsel_linux];
flags: [af_allowdirect, af_needar, af_smartlink_sections];
labelprefix: '.L';
comment: '# ';
dollarsign: '$';
);
- as_MIPS_as_info: tasminfo =
+ as_MIPSEB_as_info: tasminfo =
(
id: as_gas;
idtxt: 'AS';
asmbin: 'as';
- asmcmd: '-mips2 -W -EB -o $OBJ $ASM';
+ asmcmd: '-mips2 $NOWARN -EB $PIC -o $OBJ $ASM';
supported_targets: [system_mipseb_linux];
flags: [af_allowdirect, af_needar, af_smartlink_sections];
labelprefix: '.L';
diff --git a/mips/compiler/mips/cpunode.pas b/mips/compiler/mips/cpunode.pas
index 89ddf3058f..58f0695588 100644
--- a/mips/compiler/mips/cpunode.pas
+++ b/mips/compiler/mips/cpunode.pas
@@ -36,6 +36,7 @@ implementation
the processor specific nodes must be included
after the generic one (FK)
}
- ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset;
+ ncpuadd,ncpucall,ncpumat,ncpuinln,
+ ncpuld,ncpucnv,ncpuset;
end.
diff --git a/mips/compiler/mips/cpupara.pas b/mips/compiler/mips/cpupara.pas
index 9d77fc0914..d4c27e940e 100644
--- a/mips/compiler/mips/cpupara.pas
+++ b/mips/compiler/mips/cpupara.pas
@@ -28,7 +28,45 @@ interface
cclasses,
aasmtai,
cpubase,cpuinfo,
- symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
+ symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase,cgutils;
+
+ const
+ MIPS_MAX_OFFSET = 20;
+ MIPS_MAX_REGISTERS_USED_IN_CALL = 6;
+
+ { All ABI seem to start with $4 i.e. $a0 }
+ MIPS_FIRST_REGISTER_USED_IN_CALL = RS_R4;
+ { O32 ABI uses $a0 to $a3, i.e R4 to R7 }
+ MIPS_LAST_REGISTER_USED_IN_CALL_ABI_O32 = RS_R7;
+ { N32 ABI uses also R8 and R9 }
+ MIPS_LAST_REGISTER_USED_IN_CALL_ABI_N32 = RS_R9;
+ { The calculation below is based on the assumption
+ that all registers used for ABI calls are
+ ordered and follow each other }
+ MIPS_NB_REGISTERS_USED_IN_CALL_O32 =
+ MIPS_LAST_REGISTER_USED_IN_CALL_ABI_O32
+ - MIPS_FIRST_REGISTER_USED_IN_CALL + 1;
+ MIPS_NB_REGISTERS_USED_IN_CALL_N32 =
+ MIPS_LAST_REGISTER_USED_IN_CALL_ABI_N32
+ - MIPS_FIRST_REGISTER_USED_IN_CALL + 1;
+
+
+ { Set O32 ABI as default }
+ const
+ mips_nb_used_registers = MIPS_NB_REGISTERS_USED_IN_CALL_O32;
+
+ { Might need to be changed if we support N64 ABI later }
+ mips_sizeof_register_param = 4;
+
+ type
+ tparasupregs = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tsuperregister;
+ tparasupregsused = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of boolean;
+ tparasupregsize = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tcgsize;
+ tparasuprename = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of shortstring;
+ tparasupregsoffset = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of longint;
+
+ const
+ parasupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
type
TMIPSParaManager=class(TParaManager)
@@ -38,76 +76,77 @@ interface
{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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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
+ intparareg,
+ intparasize : longint;
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
- procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
- var intparareg,parasize:longint);
+ procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist);
end;
implementation
uses
cutils,verbose,systems,
- defutil,
- cgutils,cgobj,
- procinfo,cpupi;
+ defutil, cpupi, procinfo,
+ cgobj;
- type
- tparasupregs = array[0..3] of tsuperregister;
- pparasupregs = ^tparasupregs;
- const
- paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7);
- parainsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7);
function TMIPSParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
begin
- result:=[RS_R0..RS_R15,RS_R24..RS_R25];
+ { O32 ABI values }
+ result:=[RS_R1..RS_R15,RS_R24..RS_R25,RS_R31];
end;
function TMIPSParaManager.get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;
begin
+ { O32 ABI values }
result:=[RS_F0..RS_F19];
end;
- procedure TMIPSParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
+ procedure TMIPSParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint; def : tdef; 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.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
- { The first four parameters are passed into registers }
+ { MIPS: ABI dependent number of first parameters
+ are passed into registers }
dec(nr);
- if nr<4 then
+ if nr<mips_nb_used_registers then
begin
loc:=LOC_REGISTER;
- register:=newreg(R_INTREGISTER,(RS_R4+nr),R_SUBWHOLE);
+ register:=newreg(R_INTREGISTER,parasupregs[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:=16 + (nr-4)*4;
+ reference.offset:=nr*mips_sizeof_register_param;
end;
size:=OS_INT;
+ { Be sure to reserve enough stack space tp cope with
+ that parameter }
+ if assigned(current_procinfo) then
+ TMIPSProcinfo(current_procinfo).allocate_push_parasize((nr+1)*mips_sizeof_register_param);
end;
end;
-
{ true if a parameter is too large to copy and only the address is pushed }
function TMIPSParaManager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
begin
@@ -120,12 +159,13 @@ implementation
end;
case def.typ of
recorddef:
- result:=false;
+ { According to 032 ABI we should have }
+ result:=false;
arraydef:
- result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
- is_open_array(def) or
- is_array_of_const(def) or
- is_array_constructor(def);
+ result:=true; {(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);}
variantdef,
formaldef :
result:=true;
@@ -152,40 +192,40 @@ implementation
paraloc : pcgparalocation;
retcgsize : tcgsize;
begin
- result.init;
- result.alignment:=get_para_align(p.proccalloption);
- { void has no location }
- if is_void(def) then
+ if set_common_funcretloc_info(p,def,retcgsize,result) 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;
+ { Return is passed as var parameter,
+ in this case we use the first register R4 for it }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ if intparareg=0 then
+ inc(intparareg);
+ if side=calleeside then
+ begin
+ result.reset;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ { return is at offset zero }
+ paraloc^.reference.offset:=0;
+ paraloc^.size:=retcgsize;
+ { Reserve first register for ret_in_param }
+ if assigned(current_procinfo) then
+ begin
+ TMIPSProcInfo(current_procinfo).register_used[0]:=true;
+ TMIPSProcInfo(current_procinfo).register_size[0]:=retcgsize;
+ TMIPSProcInfo(current_procinfo).register_name[0]:='ret_in_param_result';
+ TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
+ end;
+ end
+ else
+ begin
+ getIntParaLoc(p.proccalloption,1,result.def,result);
+ end;
+ result.def:=getpointerdef(def);
+ end;
exit;
end;
-}
paraloc:=result.add_location;
{ Return in FPU register? }
@@ -232,16 +272,15 @@ implementation
end
end;
- procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
- var intparareg,parasize:longint);
+
+ procedure TMIPSParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist);
var
paraloc : pcgparalocation;
i : integer;
hp : tparavarsym;
- paradef : tdef;
paracgsize : tcgsize;
- hparasupregs : pparasupregs;
paralen : longint;
+ paradef : tdef;
fpparareg : integer;
can_use_float : boolean;
reg : tsuperregister;
@@ -250,63 +289,67 @@ implementation
begin
fpparareg := 0;
can_use_float := true;
- if side=callerside then
- hparasupregs:=@paraoutsupregs
- else
- hparasupregs:=@parainsupregs;
-
for i:=0 to paras.count-1 do
begin
hp:=tparavarsym(paras[i]);
paradef := hp.vardef;
{ currently only support C-style array of const }
- if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ 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;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_R0;
+ paraloc^.size:=OS_ADDR;
break;
end;
- if (push_addr_param(hp.varspez,paradef,p.proccalloption)) then
- begin
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ begin
paracgsize := OS_ADDR;
- paralen := tcgsize2size[paracgsize];
- end
+ paralen := tcgsize2size[paracgsize];
+ paradef := getpointerdef(paradef);
+ end
else
begin
paracgsize := def_cgsize(paradef);
{ for things like formaldef }
- if (paracgsize=OS_NO) then
+ if (paracgsize=OS_NO) and (paradef.typ <> recorddef) then
begin
paracgsize:=OS_ADDR;
+ paradef:=voidpointertype;
end;
if not is_special_array(paradef) then
paralen := paradef.size
else
paralen := tcgsize2size[paracgsize];
+ end;
- end;
-
- if (paracgsize in [OS_64, OS_S64, OS_F64]) or (hp.vardef.alignment = 8) then
+ if (paracgsize in [OS_64, OS_S64, OS_F64]) or (hp.vardef.alignment = 8) then
alignment := 8
else
alignment := 4;
hp.paraloc[side].reset;
hp.paraloc[side].Alignment:=alignment;
+ if paracgsize=OS_NO then
+ begin
+ paracgsize:=OS_32;
+ paralen:=align(paralen,4);
+ end
+ else
+ paralen:=tcgsize2size[paracgsize];
hp.paraloc[side].intsize:=paralen;
hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].def:=paradef;
{ check the alignment, mips O32ABI require a nature alignment }
- tmp := align(parasize, alignment) - parasize;
+ tmp := align(intparasize, alignment) - intparasize;
while tmp > 0 do
begin
inc(intparareg);
- inc(parasize,4);
+ inc(intparasize,4);
dec(tmp,4);
end;
@@ -319,35 +362,52 @@ implementation
begin
paraloc:=hp.paraloc[side].add_location;
{ We can allocate at maximum 32 bits per register }
- if (paracgsize in [OS_64,OS_S64]) or ((paracgsize in [OS_F32,OS_F64]) and not(can_use_float)) then
+ if (paracgsize in [OS_64,OS_S64]) or
+ ((paracgsize in [OS_F32,OS_F64]) and
+ not(can_use_float)) then
paraloc^.size:=OS_32
else
paraloc^.size:=paracgsize;
{ ret in param? }
- {if vo_is_funcret in hp.varoptions then
+ if vo_is_funcret in hp.varoptions then
begin
- paraloc^.loc:=LOC_REFERENCE;
+ { This should be the first parameter }
+ if assigned(current_procinfo) then
+ begin
+ TMIPSProcInfo(current_procinfo).register_used[0]:=true;
+ TMIPSProcInfo(current_procinfo).register_name[0]:='result';
+ TMIPSProcInfo(current_procinfo).register_size[0]:=paracgsize;
+ TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
+ end;
+ //if (intparareg<>1) then
+ // Comment(V_Warning,'intparareg should be one for funcret in TMipsParaManager.create_paraloc_info_intern');
if side=callerside then
begin
- paraloc^.reference.index := NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=parasize;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,parasupregs[0],R_SUBWHOLE);
end
else
begin
- paraloc^.reference.index := NR_FRAME_POINTER_REG;
- paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
- TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
+ paraloc^.loc:=LOC_REFERENCE;
+ if (po_nostackframe in p.procoptions) then
+ paraloc^.reference.index := NR_STACK_POINTER_REG
+ else
+ begin
+ paraloc^.reference.index := NR_FRAME_POINTER_REG;
+ if assigned(current_procinfo) then
+ TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+ paraloc^.reference.offset:=0;
end;
- inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
- inc(intparareg);
- //writeln(hs,'funcret',i,' ', parasize);
+ inc(intparasize,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
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ else if (intparareg<mips_nb_used_registers) and
(not(vo_is_parentfp in hp.varoptions) or
not(po_delphi_nested_cc in p.procoptions)) then
begin
- if (can_use_float) then
+ if (can_use_float) then
begin
paraloc^.loc:=LOC_FPUREGISTER;
if (fpparareg = 0) then
@@ -358,79 +418,111 @@ implementation
begin
paraloc^.register:=newreg(R_FPUREGISTER, reg, R_SUBFD);
inc(fpparareg);
- inc(intparareg);
- inc(intparareg);
- inc(parasize,8);
+ inc(intparareg);
+ inc(intparareg);
+ inc(intparasize,8);
end
else
begin
paraloc^.register:=newreg(R_FPUREGISTER, reg, R_SUBFS);
inc(fpparareg);
- inc(intparareg);
- inc(parasize,sizeof(aint));
+ inc(intparareg);
+ inc(intparasize,sizeof(aint));
end;
end
- else
- begin
- paraloc^.loc:=LOC_REGISTER;
- paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
- inc(intparareg);
- inc(parasize,sizeof(aint));
- end;
+ else { not can use float }
+ begin
+ if assigned(current_procinfo) then
+ begin
+ TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
+ TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
+ TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paracgsize;
+ TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
+ end;
+ if side=callerside then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,parasupregs[intparareg],R_SUBWHOLE);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if (po_nostackframe in p.procoptions) then
+ paraloc^.reference.index := NR_STACK_POINTER_REG
+ else
+ begin
+ paraloc^.reference.index := NR_FRAME_POINTER_REG;
+ if assigned(current_procinfo) then
+ TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+ paraloc^.reference.offset:=intparareg*mips_sizeof_register_param;
+ end;
+ inc(intparareg);
+ inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
+ end;
end
else
begin
paraloc^.loc:=LOC_REFERENCE;
-
if side=callerside then
begin
paraloc^.reference.index := NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=parasize;
+ paraloc^.reference.offset:=intparasize;
end
else
begin
- paraloc^.reference.index := NR_FRAME_POINTER_REG;
- paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
- TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
+ if (po_nostackframe in p.procoptions) then
+ paraloc^.reference.index := NR_STACK_POINTER_REG
+ else
+ begin
+ paraloc^.reference.index := NR_FRAME_POINTER_REG;
+ if assigned(current_procinfo) then
+ TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+ paraloc^.reference.offset:=intparasize;
end;
- inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
+ inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
end;
dec(paralen,tcgsize2size[paraloc^.size]);
- end; { while }
- end; {for}
- if (parasize < 16) then
- parasize := 16;
+ end;
+ end;
+ { O32 ABI reqires at least 16 bytes }
+ if (intparasize < 16) then
+ intparasize := 16;
+ { Increase maxpushparasize, but only if not examining itself }
+ //if assigned(current_procinfo) and (side=callerside) and
+ // (current_procinfo.procdef <> p) then
+ // begin
+ // TMIPSProcinfo(current_procinfo).allocate_push_parasize(intparasize);
+ // end;
end;
function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
- var
- intparareg,
- parasize : longint;
begin
intparareg:=0;
- parasize:=0;
+ intparasize:=0;
+ { Create Function result paraloc }
+ create_funcretloc_info(p,callerside);
{ calculate the registers for the normal parameters }
- create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize);
+ create_paraloc_info_intern(p,callerside,p.paras);
{ append the varargs }
- create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
- result:=parasize;
+ create_paraloc_info_intern(p,callerside,varargspara);
+ { We need to return the size allocated on the stack }
+ result:=intparasize;
end;
function TMIPSParaManager.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);
+ intparasize:=0;
{ Create Function result paraloc }
create_funcretloc_info(p,side);
+ create_paraloc_info_intern(p,side,p.paras);
{ We need to return the size allocated on the stack }
- result:=parasize;
+ result:=intparasize;
end;
diff --git a/mips/compiler/mips/cpupi.pas b/mips/compiler/mips/cpupi.pas
index f01be970bf..6d579faed5 100644
--- a/mips/compiler/mips/cpupi.pas
+++ b/mips/compiler/mips/cpupi.pas
@@ -27,8 +27,8 @@ interface
uses
cutils,
- globtype,
- procinfo,cpuinfo,
+ globtype,symdef,
+ procinfo,cpuinfo,cpupara,
psub;
type
@@ -40,27 +40,56 @@ interface
floatregstart : aint;
intregssave,
floatregssave : byte;
+ needs_frame_pointer: boolean;
+ register_used : tparasupregsused;
+ register_size : tparasupregsize;
+ register_name : tparasuprename;
+ register_offset : tparasupregsoffset;
+ computed_local_size : longint;
+ //intparareg,
+ //parasize : longint;
constructor create(aparent:tprocinfo);override;
function calc_stackframe_size:longint;override;
procedure set_first_temp_offset;override;
- public
- needs_frame_pointer: boolean;
end;
+ { Used by Stabs debug info generator }
+
+ function mips_extra_offset(procdef : tprocdef) : longint;
+
implementation
uses
- systems,globals,
- cpubase,cgbase,cgobj,
+ systems,globals,verbose,
+ cpubase,cgbase,cgutils,cgobj,
tgobj,paramgr,symconst;
constructor TMIPSProcInfo.create(aparent: tprocinfo);
+ var
+ i : longint;
begin
inherited create(aparent);
+ for i:=low(tparasupregs) to high(tparasupregs) do
+ begin
+ register_used[i]:=false;
+ register_size[i]:=OS_NO;
+ register_name[i]:='invalid';
+ register_offset[i]:=-1;
+ end;
floatregssave:=12; { f20-f31 }
intregssave:=12; { r16-r23,r28-r31 }
- needs_frame_pointer := false;
- maxpushedparasize := 16;
+ { for testing }
+ needs_frame_pointer := true;//false;
+ computed_local_size:=-1;
+ { pi_needs_got is not yet set correctly
+ so include it always if creating PIC code }
+ if (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ include(flags, pi_needs_got);
+ got:=NR_GP;
+ end
+ else
+ got:=NR_NO;
end;
@@ -72,7 +101,8 @@ implementation
if tg.direction = -1 then
tg.setfirsttemp(0)
else
- tg.setfirsttemp(maxpushedparasize+floatregssave*sizeof(aint)+intregssave*sizeof(aint));
+ tg.setfirsttemp(maxpushedparasize+
+ floatregssave*sizeof(aint)+intregssave*sizeof(aint));
end;
@@ -82,14 +112,27 @@ implementation
regs: tcpuregisterset;
begin
result:=maxpushedparasize;
- { ABI requirement: start of the register save area must align at 8 byte }
- { can we ensure maxpushedparasize is properly aligned? if so unnecessary}
- floatregstart:=Align(result,8);
+ floatregstart:=result;
inc(result,floatregssave*4);
intregstart:=result;
+ //inc(result,intregssave*4);
result:=Align(tg.lasttemp,max(current_settings.alignment.localalignmin,8));
+ if computed_local_size=-1 then
+ begin
+ computed_local_size:=result;
+ procdef.total_local_size:=result;
+ end
+ else if computed_local_size <> result then
+ Comment(V_Error,'TMIPSProcInfo.calc_stackframe_size result changed');
end;
+ function mips_extra_offset(procdef : tprocdef) : longint;
+ begin
+ if procdef=nil then
+ mips_extra_offset:=0
+ else
+ mips_extra_offset:=procdef.total_local_size;
+ end;
begin
cprocinfo:=TMIPSProcInfo;
diff --git a/mips/compiler/mips/hlcgcpu.pas b/mips/compiler/mips/hlcgcpu.pas
index ecffd1b79b..ad03bee126 100644
--- a/mips/compiler/mips/hlcgcpu.pas
+++ b/mips/compiler/mips/hlcgcpu.pas
@@ -28,17 +28,82 @@ unit hlcgcpu;
interface
+uses
+ globtype,
+ aasmbase, aasmdata,
+ cgbase, cgutils,
+ symdef,
+ hlcgobj, hlcg2ll;
+
+ type
+ thlcg2mips = class(thlcg2ll)
+ procedure a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean);override;
+ procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override;
+ procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override;
+ end;
+
procedure create_hlcodegen;
implementation
uses
- hlcgobj, hlcg2ll,
+ aasmtai,
+ cutils,
+ cgobj,
+ cpubase,
cgcpu;
+ procedure thlcg2mips.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean);
+ var
+ ref : treference;
+ begin
+ if pd.proccalloption=pocall_cdecl then
+ begin
+ { Use $gp/$t9 registers as the code might be in a shared library }
+ reference_reset(ref,sizeof(aint));
+ ref.symbol:=current_asmdata.RefAsmSymbol('_gp');
+ list.concat(tai_comment.create(strpnew('Using PIC code for a_call_name')));
+ cg.a_loadaddr_ref_reg(list,ref,NR_GP);
+ reference_reset(ref,sizeof(aint));
+ ref.symbol:=current_asmdata.RefAsmSymbol(s);
+ ref.base:=NR_GP;
+ ref.refaddr:=addr_pic;
+ cg.a_loadaddr_ref_reg(list,ref,NR_PIC_FUNC);
+ cg.a_call_reg(list,NR_PIC_FUNC);
+ end
+ else
+ cg.a_call_name(list,s,weak);
+ end;
+
+ procedure thlcg2mips.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister);
+ begin
+ if (pd.proccalloption=pocall_cdecl) and (reg<>NR_PIC_FUNC) then
+ begin
+ list.concat(tai_comment.create(strpnew('Using PIC code for a_call_reg')));
+ { Use $t9 register as the code might be in a shared library }
+ cg.a_load_reg_reg(list,OS_32,OS_32,reg,NR_PIC_FUNC);
+ cg.a_call_reg(list,NR_PIC_FUNC);
+ end
+ else
+ cg.a_call_reg(list,reg);
+ end;
+
+ procedure thlcg2mips.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference);
+ begin
+ if pd.proccalloption =pocall_cdecl then
+ begin
+ { Use $t9 register as the code might be in a shared library }
+ list.concat(tai_comment.create(strpnew('Using PIC code for a_call_ref')));
+ cg.a_loadaddr_ref_reg(list,ref,NR_PIC_FUNC);
+ cg.a_call_reg(list,NR_PIC_FUNC);
+ end
+ else
+ cg.a_call_ref(list,ref);
+ end;
+
procedure create_hlcodegen;
begin
- hlcg:=thlcg2ll.create;
+ hlcg:=thlcg2mips.create;
create_codegen;
end;
diff --git a/mips/compiler/mips/mipsreg.dat b/mips/compiler/mips/mipsreg.dat
index 9e47712691..9e4be25b0e 100644
--- a/mips/compiler/mips/mipsreg.dat
+++ b/mips/compiler/mips/mipsreg.dat
@@ -37,47 +37,47 @@ R27,$01,$04,$1B,k1,$27,27,27
R28,$01,$04,$1C,gp,$28,28,28
R29,$01,$04,$1D,sp,$29,29,29
R30,$01,$04,$1E,fp,$30,30,30
-R31,$01,$04,$1F,$a,$31,31,31
+R31,$01,$04,$1F,ra,$31,31,31
-F0,$02,$06,$00,F0,$f0,32,32
-F1,$02,$06,$01,F1,$f1,33,33
-F2,$02,$06,$02,F2,$f2,34,34
-F3,$02,$06,$03,F3,$f3,35,35
-F4,$02,$06,$04,F4,$f4,36,36
-F5,$02,$06,$05,F5,$f5,37,37
-F6,$02,$06,$06,F6,$f6,38,38
-F7,$02,$06,$07,F7,$f7,39,39
-F8,$02,$06,$08,F8,$f8,40,40
-F9,$02,$06,$09,F9,$f9,41,41
-F10,$02,$06,$0A,F10,$f10,42,42
-F11,$02,$06,$0B,F11,$f11,43,43
-F12,$02,$06,$0C,F12,$f12,44,44
-F13,$02,$06,$0D,F13,$f13,45,45
-F14,$02,$06,$0E,F14,$f14,46,46
-F15,$02,$06,$0F,F15,$f15,47,47
-F16,$02,$06,$10,F16,$f16,48,48
-F17,$02,$06,$11,F17,$f17,49,49
-F18,$02,$06,$12,F18,$f18,50,50
-F19,$02,$06,$13,F19,$f19,51,51
-F20,$02,$06,$14,F20,$f20,52,52
-F21,$02,$06,$15,F21,$f21,53,53
-F22,$02,$06,$16,F22,$f22,54,54
-F23,$02,$06,$17,F23,$f23,55,55
-F24,$02,$06,$18,F24,$f24,56,56
-F25,$02,$06,$19,F25,$f25,57,57
-F26,$02,$06,$1A,F26,$f26,58,58
-F27,$02,$06,$1B,F27,$f27,59,59
-F28,$02,$06,$1C,F28,$f28,60,60
-F29,$02,$06,$1D,F29,$f29,61,61
-F30,$02,$06,$1E,F30,$f30,62,62
-F31,$02,$06,$1F,F31,$f31,63,63
+F0,$02,$06,$00,f0,$f0,32,32
+F1,$02,$06,$01,f1,$f1,33,33
+F2,$02,$06,$02,f2,$f2,34,34
+F3,$02,$06,$03,f3,$f3,35,35
+F4,$02,$06,$04,f4,$f4,36,36
+F5,$02,$06,$05,f5,$f5,37,37
+F6,$02,$06,$06,f6,$f6,38,38
+F7,$02,$06,$07,f7,$f7,39,39
+F8,$02,$06,$08,f8,$f8,40,40
+F9,$02,$06,$09,f9,$f9,41,41
+F10,$02,$06,$0A,f10,$f10,42,42
+F11,$02,$06,$0B,f11,$f11,43,43
+F12,$02,$06,$0C,f12,$f12,44,44
+F13,$02,$06,$0D,f13,$f13,45,45
+F14,$02,$06,$0E,f14,$f14,46,46
+F15,$02,$06,$0F,f15,$f15,47,47
+F16,$02,$06,$10,f16,$f16,48,48
+F17,$02,$06,$11,f17,$f17,49,49
+F18,$02,$06,$12,f18,$f18,50,50
+F19,$02,$06,$13,f19,$f19,51,51
+F20,$02,$06,$14,f20,$f20,52,52
+F21,$02,$06,$15,f21,$f21,53,53
+F22,$02,$06,$16,f22,$f22,54,54
+F23,$02,$06,$17,f23,$f23,55,55
+F24,$02,$06,$18,f24,$f24,56,56
+F25,$02,$06,$19,f25,$f25,57,57
+F26,$02,$06,$1A,f26,$f26,58,58
+F27,$02,$06,$1B,f27,$f27,59,59
+F28,$02,$06,$1C,f28,$f28,60,60
+F29,$02,$06,$1D,f29,$f29,61,61
+F30,$02,$06,$1E,f30,$f30,62,62
+F31,$02,$06,$1F,f31,$f31,63,63
PC,$05,$00,$00,PC,pc,-1,-1
HI,$05,$00,$01,HI,hi,68,68
LO,$05,$00,$02,LO,lo,69,69
CR,$05,$00,$03,CR,cr,70,70
-FCR0,$05,$00,$04,FCR0,fcr0,71,71
-FCR25,$05,$00,$05,FCR25,fcr25,72,72
-FCR26,$05,$00,$06,FCR26,fcr26,73,73
-FCR28,$05,$00,$07,FCR28,fcr28,74,74
-FCSR,$05,$00,$08,FCSR,fcsr,75,75
+FCR0,$05,$00,$04,fcr0,fcr0,71,71
+FCR25,$05,$00,$05,fcr25,fcr25,72,72
+FCR26,$05,$00,$06,fcr26,fcr26,73,73
+FCR28,$05,$00,$07,fcr28,fcr28,74,74
+FCSR,$05,$00,$08,fcsr,fcsr,75,75
diff --git a/mips/compiler/mips/ncpucall.pas b/mips/compiler/mips/ncpucall.pas
index 450b3802b7..6477c9c789 100644
--- a/mips/compiler/mips/ncpucall.pas
+++ b/mips/compiler/mips/ncpucall.pas
@@ -26,10 +26,11 @@ unit ncpucall;
interface
uses
- ncgcal;
+ node, ncgcal;
type
tMIPSELcallnode = class(tcgcallnode)
+ function pass_1 : tnode; override;
procedure extra_call_code; override;
procedure extra_post_call_code; override;
end;
@@ -38,11 +39,20 @@ type
implementation
uses
- cpubase,
+ globtype,cpubase,procinfo,
aasmtai,aasmcpu,aasmdata,
paramgr,
ncal;
+function TMIPSELcallnode.pass_1 : tnode;
+begin
+ pass_1 := inherited pass_1;
+ if assigned(current_procinfo) and
+ assigned(procdefinition) and
+ (procdefinition.proccalloption=pocall_cdecl) then
+ include(current_procinfo.flags,pi_needs_got);
+end;
+
procedure tMIPSELcallnode.extra_call_code;
begin
{ MIPS functions should never modify the stack pointer
diff --git a/mips/compiler/mips/ncpuld.pas b/mips/compiler/mips/ncpuld.pas
new file mode 100644
index 0000000000..75c103da28
--- /dev/null
+++ b/mips/compiler/mips/ncpuld.pas
@@ -0,0 +1,72 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate MIPS 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 ncpuld;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ncgld;
+
+type
+ tmipsloadnode = class(tcgloadnode)
+ function pass_1 : tnode; override;
+ procedure generate_picvaraccess; override;
+ end;
+
+implementation
+
+uses
+ verbose,
+ globtype,
+ systems,
+ cpubase,
+ cgbase, cgutils, cgobj,
+ aasmbase, aasmtai,aasmdata,
+ symconst, symsym,
+ procinfo,
+ nld;
+
+function tmipsloadnode.pass_1 : tnode;
+begin
+ pass_1 := inherited pass_1;
+ case symtableentry.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ if([vo_is_dll_var,vo_is_external] * tabstractvarsym(symtableentry).varoptions <> []) then
+ include(current_procinfo.flags,pi_needs_got);
+ end;
+end;
+
+procedure tmipsloadnode.generate_picvaraccess;
+begin
+ location.reference.base:=current_procinfo.got;
+ location.reference.refaddr:=addr_pic;
+ location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
+end;
+
+begin
+ cloadnode := tmipsloadnode;
+end.
+
diff --git a/mips/compiler/mips/opcode.inc b/mips/compiler/mips/opcode.inc
index 1f15252bbb..350c9c4545 100644
--- a/mips/compiler/mips/opcode.inc
+++ b/mips/compiler/mips/opcode.inc
@@ -9,6 +9,9 @@ A_P_FRAME,
A_P_MASK,
A_P_FMASK,
A_P_SW,
+A_P_CPLOAD,
+A_P_CPRESTORE,
+A_P_CPADD,
A_SPARC8UNIMP,
A_NOP,
A_NOT,
diff --git a/mips/compiler/mips/rmipssri.inc b/mips/compiler/mips/rmipssri.inc
index 84a19da2f2..3e297e23a4 100644
--- a/mips/compiler/mips/rmipssri.inc
+++ b/mips/compiler/mips/rmipssri.inc
@@ -1,6 +1,14 @@
{ don't edit, this file is generated from mipsreg.dat }
-32,
68,
+66,
+0,
+67,
+65,
+5,
+6,
+7,
+8,
+2,
33,
34,
43,
@@ -38,19 +46,11 @@
71,
72,
73,
-66,
-0,
-67,
-65,
-5,
-6,
-7,
-8,
-2,
31,
29,
27,
28,
+32,
17,
18,
19,
diff --git a/mips/compiler/mips/rmipsstd.inc b/mips/compiler/mips/rmipsstd.inc
index f03b0d33cb..1b23ada747 100644
--- a/mips/compiler/mips/rmipsstd.inc
+++ b/mips/compiler/mips/rmipsstd.inc
@@ -31,45 +31,45 @@
'gp',
'sp',
'fp',
-'$a',
-'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',
+'ra',
+'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'
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'
diff --git a/mips/compiler/mips/strinst.inc b/mips/compiler/mips/strinst.inc
index ccab5b5e0c..d55f207fe1 100644
--- a/mips/compiler/mips/strinst.inc
+++ b/mips/compiler/mips/strinst.inc
@@ -9,6 +9,9 @@
'.mask',
'.fmask',
'p_sw',
+'.cpload',
+'.cprestore',
+'.cpadd',
'sparc8unimp',
'nop',
'not',
diff --git a/mips/compiler/msg/errore.msg b/mips/compiler/msg/errore.msg
index 190b1adf2a..bc90ddac13 100644
--- a/mips/compiler/msg/errore.msg
+++ b/mips/compiler/msg/errore.msg
@@ -390,7 +390,7 @@ scan_w_unavailable_system_codepage=02091_W_Current system codepage "$1" is not a
#
# Parser
#
-# 03321 is the last used one
+# 03322 is the last used one
#
% \section{Parser messages}
% This section lists all parser messages. The parser takes care of the
@@ -1199,8 +1199,8 @@ parser_e_forward_mismatch=03249_E_Forward type definition does not match
% 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.
+% unexpected results. E.g., in case the new visibility is private then 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
@@ -1444,6 +1444,8 @@ parser_e_jvm_invalid_virtual_constructor_call=03321_E_Calling a virtual construc
% The JVM does not natively support virtual constructor. Unforunately, we are not aware of a way to
% emulate them in a way that makes it possible to support calling virtual constructors
% for the current instance inside another constructor.
+parser_e_method_lower_visibility=03322_E_Overring method "$1" cannot have a lower visibility ($2) than in parent class $3 ($4)
+% The JVM does not allow lowering the visibility of an overriding method.
% \end{description}
# Type Checking
#
@@ -3317,6 +3319,7 @@ J*2CT<x>_Target-specific code generation options
p*3CTsmalltoc_ Generate smaller TOCs at the expense of execution speed (AIX)
P*3CTsmalltoc_ Generate smaller TOCs at the expense of execution speed (AIX)
J*3CTcompactintarrayinit_ Generate smaller (but potentially slower) code for initializing integer array constants
+K*3CTenumfieldinit_ Initialize enumeration fields in constructors to enumtype(0), after calling inherited constructors
J*2Cv_Var/out parameter copy-out checking
**2CX_Create also smartlinked library
**1d<x>_Defines the symbol <x>
diff --git a/mips/compiler/msgidx.inc b/mips/compiler/msgidx.inc
index 8d1dcdd12c..ec61df0ce9 100644
--- a/mips/compiler/msgidx.inc
+++ b/mips/compiler/msgidx.inc
@@ -416,6 +416,7 @@ const
parser_d_internal_parser_string=03319;
parser_e_feature_unsupported_for_vm=03320;
parser_e_jvm_invalid_virtual_constructor_call=03321;
+ parser_e_method_lower_visibility=03322;
type_e_mismatch=04000;
type_e_incompatible_types=04001;
type_e_not_equal_types=04002;
@@ -943,9 +944,9 @@ const
option_info=11024;
option_help_pages=11025;
- MsgTxtSize = 65789;
+ MsgTxtSize = 66002;
MsgIdxMax : array[1..20] of longint=(
- 26,92,322,118,87,56,116,26,202,63,
+ 26,92,323,118,87,56,116,26,202,63,
53,20,1,1,1,1,1,1,1,1
);
diff --git a/mips/compiler/msgtxt.inc b/mips/compiler/msgtxt.inc
index e9fcac859e..73a95c0174 100644
--- a/mips/compiler/msgtxt.inc
+++ b/mips/compiler/msgtxt.inc
@@ -1,7 +1,7 @@
{$ifdef Delphi}
-const msgtxt : array[0..000274] of string[240]=(
+const msgtxt : array[0..000275] of string[240]=(
{$else Delphi}
-const msgtxt : array[0..000274,1..240] of char=(
+const msgtxt : array[0..000275,1..240] of char=(
{$endif Delphi}
'01000_T_Compiler: $1'#000+
'01001_D_Compiler OS: $1'#000+
@@ -514,636 +514,632 @@ const msgtxt : array[0..000274,1..240] of char=(
'03320_E_This language feature is not supported on managed VM targets'#000+
'03321_E_Calling a virtual constructor for the current instance inside '+
'another constructor is not possible',' on the JVM target'#000+
+ '03322_E_Overring method "$1" cannot have a lower visibility ($2) than '+
+ 'in parent class $3 ($4)'#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+
+ '04003_E_Ty','pe identifier expected'#000+
'04004_E_Variable identifier expected'#000+
- '04005_E_Integer expression expecte','d, but got "$1"'#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+
+ '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_S','et elements are not compatible'#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+
+ 'an',' integer type'#000+
'04015_H_use DIV instead to get an integer result'#000+
- '04016_E_String types have to ma','tch exactly in $V+ mode'#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+
+ '04019_E_Can',#039't use readln or writeln on typed file'#000+
'04020_E_Can'#039't use read or write on untyped file.'#000+
- '04021_','E_Type conflict between set elements'#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+
+ '040','24_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 expressions'#000+
+ '0402','8_E_Can'#039't take the address of constant expressions'#000+
'04029_E_Argument can'#039't be assigned to'#000+
- '04030','_E_Can'#039't assign local procedure/function to procedure varia'+
- 'ble'#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+
+ '04032_E_Can'#039't assign values to const vari','able'#000+
'04033_E_Array type required'#000+
'04034_E_interface type expected, but got "$1"'#000+
- '04035_H_Mixing ','signed expressions and longwords gives a 64bit result'+
- #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 assignment'#000+
- '04038_E_enums with assignments can'#039't be us','ed as array index'#000+
+ '04037_E_T','ypecast has different size ($1 -> $2) in assignment'#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+
+ '04041_E_Class or i','nterface type expected, but got "$1"'#000+
'04042_E_Type "$1" is not completely defined'#000+
- '04043_W_Strin','g literal has more characters than short string length'#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 constant and e'+
- 'xpression'#000+
- '04046_W_Constructing a c','lass "$1" with abstract method "$2"'#000+
+ '04045_W_Co','mparison might be always true due to range of constant 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 mismatch, possible loss of data / range check error',
- #000+
+ '04048_W_Type size mismatch, possible loss of ','data / range check erro'+
+ 'r'#000+
+ '04049_H_Type size mismatch, possible loss of data / range check error'#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+
+ '04052_E_Consta','nt Expression expected'#000+
'04053_E_Operation "$1" not supported for types "$2" and "$3"'#000+
- '04054_E_Il','legal type conversion: "$1" to "$2"'#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+
+ '04056_W_Conversion between ordinals and point','ers is not portable'#000+
'04057_E_Can'#039't determine which overloaded function to call'#000+
- '04058_E_Illegal ','counter variable'#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 supporte','d'#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+
+ '04063_E_Incompatible type for arg no. $1: Got "$2" expected "(no','t pa'+
+ 'cked) Array"'#000+
'04064_E_Elements of packed arrays cannot be of a type which need to be'+
- ' initia','lised'#000+
+ ' 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+
+ 'gest',' typecast'#000+
'04076_E_Can'#039't take address of a subroutine marked as local'#000+
- '04077_E_Can'#039't export subr','outine marked as local from a unit'#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+
+ 'ven','t overflow errors.'#000+
'04080_H_Converting the operands to "$1" before doing the subtract coul'+
- 'd pre','vent overflow errors.'#000+
+ 'd 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'+
- 'parison results and range errors, use an unsigned t','ype instead.'#000+
+ '04082_W_Converting pointers',' to signed integers may result in wrong c'+
+ 'omparison 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+
+ '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" is not supported for interaction with the Objec',
- 'tive-C runtime.'#000+
+ '04091_E_Objective-C protocol typ','e expected, but got "$1"'#000+
+ '04092_E_The type "$1" is not supported for interaction with the Object'+
+ 'ive-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 corruption: $1 to $2'#000+
- '04096_E_Type parameters of spec','ializations of generics cannot refere'+
- 'nce the currently specialized type'#000+
+ '04095_W_Coerced univ parameter type in proc','edural variable may cause'+
+ ' crash or memory corruption: $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+
+ 'ject',' procedure or function'#000+
'04098_E_Generic declaration of "$1" differs from previous declaration'#000+
- '0','4099_E_Helper type expected'#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+
+ '04102_E_D','erived record helper must extend "$1"'#000+
'04103_E_Invalid assignment, procedures return no value'#000+
- '0','4104_W_Implicit string type conversion from "$1" to "$2"'#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+
- '04107_-W_Explicit string typecast with potential',' data loss from "$1"'+
- ' to "$2"'#000+
+ '04106_','-W_Explicit string typecast from "$1" to "$2"'#000+
+ '04107_-W_Explicit string typecast with potential data loss from "$1" t'+
+ 'o "$2"'#000+
'04108_W_Unicode constant cast with potential data loss'#000+
- '04109_E_range check error while evaluating constants ($1 must be betwe'+
- 'en $2 and $3)'#000+
+ '04109_E_range check error while evaluating constants ($1 must ','be bet'+
+ 'ween $2 and $3)'#000+
'04110_W_range check error while evaluating constants ($1 must be betwe'+
- 'en',' $2 and $3)'#000+
+ 'en $2 and $3)'#000+
'04111_E_This type is not supported for the Default() intrinsic'#000+
'04112_E_JVM virtual class methods cannot be static'#000+
- '04113_E_Final (class) fields can only be assigned in their class'#039' '+
- '(class) constructor'#000+
- '04114_E_It is not possible t','o typecast untyped parameters on managed'+
- ' platforms, simply assign a value to them instead.'#000+
- '04115_E_The assignment side of an expression cannot be typecasted to a'+
- ' supertype on managed platforms'#000+
- '04116_-W_The interface method "$1" raises the v','isibility of "$2" to '+
- 'public when accessed via an interface instance'#000+
+ '04113_E_Final (class',') fields can only be assigned in their class'#039+
+ ' (class) constructor'#000+
+ '04114_E_It is not possible to typecast untyped parameters on managed p'+
+ 'latforms, simply assign a value to them instead.'#000+
+ '04115_E_The assignment side of an expression cannot be ','typecasted to'+
+ ' a supertype on managed platforms'#000+
+ '04116_-W_The interface method "$1" raises the visibility of "$2" to pu'+
+ 'blic when accessed via an interface instance'#000+
'04117_E_The interface method "$1" has a higher visibility (public) tha'+
'n "$2"'#000+
- '05000_E_Identifier not found "$1"'#000+
+ '0','5000_E_Identifier not found "$1"'#000+
'05001_F_Internal Error in SymTableStack()'#000+
- '05002_E_Duplicate i','dentifier "$1"'#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+
+ '050','07_E_Error in type definition'#000+
'05009_E_Forward type not resolved "$1"'#000+
- '05010_E_Only static varia','bles can be used in static methods or outsi'+
- 'de methods'#000+
+ '05010_E_Only static variables can be used in static methods or outside'+
+ ' 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+
+ '05013_E_Instances of classes or objects with an abstra','ct method are '+
+ 'not allowed'#000+
'05014_W_Label not defined "$1"'#000+
- '05015_E_Label used but not defined "$','1"'#000+
+ '05015_E_Label used but not defined "$1"'#000+
'05016_E_Illegal 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+
+ '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_F','orward class definition not resolved "$1"'#000+
+ '05022_E_Forward class definition 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+
+ '05','026_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+
+ '05030_N_Private field "$1.$2" is assigned but never u','sed'#000+
'05031_N_Private method "$1.$2" never used'#000+
'05032_E_Set type expected'#000+
- '05033_W_Function resul','t does not seem to be set'#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+
+ '05036_W_','Local variable "$1" does not seem to be initialized'#000+
+ '05037_W_Variable "$1" does not seem to be initialized'#000+
'05038_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+
+ '05042_E_No matching implementati','on for interface method "$1" found'#000+
'05043_W_Symbol "$1" is deprecated'#000+
- '05044_W_Symbol "$1" is no','t portable'#000+
+ '05044_W_Symbol "$1" is not portable'#000+
'05055_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+
+ '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 vari','able does not seem to initialized'#000+
+ '05059_W_Function result variable does not seem to initialized'#000+
'05060_H_Function result variable does not seem to be initialized'#000+
- '05061_W_Variable "$1" read but nowhere assigned'#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 declara','tion "$1" not resolved, assumed external'#000+
+ '05064_W_Forward declaration "$1" not resolved, 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+
+ '05067_E_Cannot find a','n enumerator for the type "$1"'#000+
'05068_E_Cannot find a "MoveNext" method in enumerator "$1"'#000+
- '0506','9_E_Cannot find a "Current" property 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+
+ 'olons in message str','ing.'#000+
'05071_N_Private type "$1.$2" never used'#000+
'05072_N_Private const "$1.$2" never used'#000+
- '05073_N_','Private property "$1.$2" never used'#000+
+ '05073_N_Private property "$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+
+ '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+
+ '05079_W_Unit "$1" is experimental'#000+
'05080_E_No complete definition of the formally declared class "$1" is '+
'in scope'#000+
- '05081_E_Gotos into initialization or finalization blocks of units are '+
- 'not allowed'#000+
+ '05081_E_Gotos into initialization or finalization bloc','ks of units ar'+
+ 'e not allowed'#000+
'05082_E_Invalid external name "$1" for formal class "$2"'#000+
- '05083_E_C','omplete class definition with external name "$1" here'#000+
+ '05083_E_Complete class definition with external name "$1" here'#000+
'05084_W_Possible library conflict: symbol "$1" from library "$2" also '+
- 'found in library "$3"'#000+
+ 'found in library "$3"'#000,
'05085_E_Cannot add implicit constructor '#039'Create'#039' because ident'+
'ifier already used by "$1"'#000+
- '05086','_E_Cannot generate default constructor for class, because paren'+
- 't has no parameterless constructor'#000+
- '06009_E_Parameter list size exceeds 65535 bytes'#000+
+ '05086_E_Cannot generate default constructor for class, because parent '+
+ 'has no parameterless constructor'#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+
+ '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+
+ '06018_W_unr','eachable code'#000+
'06020_E_Abstract methods can'#039't be called directly'#000+
- '06027_DL_Register $1 weight $2',' $3'#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+
+ '06033_E_No code for i','nline procedure stored'#000+
'06035_E_Element zero of an ansi/wide- or longstring can'#039't be acces'+
- 'sed, ','use (set)length instead'#000+
+ 'sed, 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+
+ '06038_E_Cannot call message handler methods di','rectly'#000+
'06039_E_Jump in or outside of an exception block'#000+
- '06040_E_Control flow statements aren'#039't',' allowed in a finally bloc'+
- 'k'#000+
+ '06040_E_Control flow statements aren'#039't allowed in a finally block'#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+
+ '060','43_E_Local variables size exceeds supported limit'#000+
'06044_E_BREAK not allowed'#000+
- '06045_E_CONTINUE n','ot 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+
+ '06047_F_Cannot find system type "$1". Check if you us','e the correct r'+
+ 'un time library.'#000+
'06048_H_Inherited call to abstract method ignored'#000+
- '06049_E_Goto',' label "$1" not defined or optimized away'#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+
- '06052_E_Label must be defined in the sa','me scope as it is declared'#000+
+ '06051_E_Inter','procedural gotos are allowed only to outer subroutines'#000+
+ '06052_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'+
- 'tient'#000+
+ '06054_E_In ISO m','ode, the mod operator is defined only for positive q'+
+ 'uotient'#000+
'06055_DL_Auto inlining: $1'#000+
- '07000_D','L_Starting $1 styled assembler parsing'#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+
+ '07004_E_Error building r','ecord offset'#000+
'07005_E_OFFSET used without identifier'#000+
'07006_E_TYPE used without identifier'#000+
- '07007','_E_Cannot use local variable or parameters here'#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+
+ '07010_E_Cannot use multiple relocatable',' symbols'#000+
'07011_E_Relocatable symbol can only be added'#000+
'07012_E_Invalid constant expression'#000+
- '0701','3_E_Relocatable symbol is not allowed'#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+
+ '07016_E_Local symbols/labels are','n'#039't allowed as references'#000+
'07017_E_Invalid base and index register usage'#000+
- '07018_W_Possible error',' in object field handling'#000+
+ '07018_W_Possible 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+
+ '07022_E_Invalid ','string as opcode operand: $1'#000+
'07023_W_@CODE and @DATA not supported'#000+
- '07024_E_Null label referenc','es are not allowed'#000+
+ '07024_E_Null label 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+
+ '07028_E_Invalid symbol r','eference'#000+
'07029_W_Fwait can cause emulation problems with emu387'#000+
- '07030_W_$1 without operand tra','nslated into $1P'#000+
+ '07030_W_$1 without operand 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+
+ '07033_E_Unsupported ','symbol type for operand'#000+
'07034_E_Constant value out of bounds'#000+
- '07035_E_Error converting decimal ','$1'#000+
+ '07035_E_Error converting 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+
+ '07040_','W_$1 is associated to an overloaded function'#000+
'07041_E_Cannot use SELF outside a method'#000+
- '07042_E_','Cannot use OLDEBP outside a nested procedure'#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 source size ','do not match'#000+
+ '07045_E_Size suffix a','nd destination or source size do not match'#000+
+ '07046_W_Size suffix and destination or source 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+
+ '07050_E_A','ssembler syntax error in constant'#000+
'07051_E_Invalid String expression'#000+
- '07052_W_constant with symb','ol $1 for address which is not on a pointe'+
- 'r'#000+
+ '07052_W_constant with symbol $1 for address which is not on a pointer'#000+
'07053_E_Unrecognized opcode $1'#000+
'07054_E_Invalid or missing opcode'#000+
- '07055_E_Invalid combination of prefix and opcode: $1'#000+
+ '07055_E_Invalid combination of prefix',' and opcode: $1'#000+
'07056_E_Invalid combination of override and opcode: $1'#000+
- '07057_E_Too many operan','ds on line'#000+
+ '07057_E_Too many 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+
+ '07062_E_Unknown label iden','tifier $1'#000+
'07063_E_Invalid register name'#000+
'07064_E_Invalid floating point register name'#000+
- '07066_W_M','odulo not supported'#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+
+ '07070_E_Cannot ','index a local var or parameter with a register'#000+
'07071_E_Invalid segment override expression'#000+
- '070','72_W_Identifier $1 supposed external'#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+
+ '07075_E_assembler code not ret','urned to text section'#000+
'07076_E_Not a directive or local symbol $1'#000+
- '07077_E_Using a defined name ','as a local label'#000+
+ '07077_E_Using a defined 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+
+ '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 acce','ss fields of objects/classes directly'#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+
+ '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)" tra','nslated into "$1 %st,%st(n)"'#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+
+ '0','7093_W_ALIGN not supported'#000+
'07094_E_Inc and Dec cannot be together'#000+
- '07095_E_Invalid reglist for ','movem'#000+
+ '07095_E_Invalid reglist 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+
+ '07098_W_No size specified and unable to determine the size of the o','p'+
+ 'erands, using DWORD as default'#000+
'07099_E_Syntax error while trying to parse a shifter operand'#000+
- '0','7100_E_Address of packed component is not at a byte boundary'#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+
+ 'ands, using BYT','E 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+
+ '07103_W_Use of +offset(%ebp) is not compatible with regcall convention'+
+ #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 combinati','on with a virtual method,'+
- ' and "$1" is not virtual'#000+
+ '07105_W_Use of -offset(%e','sp), access may cause a crash or value may '+
+ 'be lost'#000+
+ '07106_E_VMTOffset must be used in combination with a virtual method, a'+
+ 'nd "$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+
+ '07108_E_All registers in a register set mu','st be of the same kind and'+
+ ' width'#000+
'07109_E_A register set cannot be empty'#000+
- '07110_W_@GOTPCREL is u','seless and potentially dangereous for local sy'+
- 'mbols'#000+
+ '07110_W_@GOTPCREL is useless and potentially dangereous for local symb'+
+ 'ols'#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 assembler procedu','res'+
- #000+
+ '071','13_E_Invalid register for $1'#000+
+ '07114_E_SEH directives are allowed only in pure assembler 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+
+ '08001_F_Selected assembler output not supporte','d'#000+
'08002_F_Comp not supported'#000+
'08003_F_Direct not support for binary writers'#000+
- '08004_E_Allocating ','of data is only allowed in bss section'#000+
+ '08004_E_Allocating 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+
+ '08007_E_Asm: $1 invalid combination o','f opcode and operands'#000+
'08008_E_Asm: 16 Bit references not supported'#000+
- '08009_E_Asm: Invalid effect','ive address'#000+
+ '08009_E_Asm: Invalid 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+
+ '08013_','E_Asm: Undefined label $1'#000+
'08014_E_Asm: Comp type not supported for this target'#000+
- '08015_E_Asm: Ex','tended 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+
+ '08019_E_','Asm: Invalid register $1'#000+
'08020_E_Asm: 16 or 32 Bit references not supported'#000+
- '08021_E_Asm: 64 Bi','t operands 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+
+ '08023_E_Missing .seh_endprologue direct','ive'#000+
'08024_E_Function prologue exceeds 255 bytes'#000+
- '08025_E_.seh_handlerdata directive without pre','ceding .seh_handler'#000+
+ '08025_E_.seh_handlerdata directive without 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+
+ '09003_E_Can'#039't c','reate 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+
+ '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+
+ '09008_E_Can'#039't call the asse','mbler, error $1 switching to external'+
+ ' assembling'#000+
'09009_I_Assembling $1'#000+
- '09010_I_Assembling with',' smartlinking $1'#000+
+ '09010_I_Assembling 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+
+ '0901','4_E_Can'#039't call the linker, switching to external linking'#000+
'09015_I_Linking $1'#000+
- '09016_E_Util $1 no','t found, switching to external linking'#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+
+ '09019_E_Creation of Dynamic/Shared Libr','aries not supported'#000+
'09020_I_Closing script $1'#000+
- '09021_E_resource compiler "$1" not found, switch','ing to external mode'+
- #000+
+ '09021_E_resource compiler "$1" not found, 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, switching t','o static link'+
- 'ing'#000+
+ '09024_T_unit $1 can'#039't be',' smart linked, switching to static linki'+
+ 'ng'#000+
+ '09025_T_unit $1 can'#039't be shared linked, switching to static linkin'+
+ 'g'#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+
+ '09028_D_Calling resource compile','r "$1" with "$2" as command line'#000+
'09029_E_Error while compiling resources'#000+
- '09030_E_Can'#039't call th','e resource compiler "$1", switching to exte'+
- 'rnal mode'#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+
+ '09033_N_File "$1','" not found for backquoted cat command'#000+
'09128_F_Can'#039't post process executable $1'#000+
- '09129_F_Can'#039't ','open executable $1'#000+
+ '09129_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+
+ '09133_X_','Stack space reserved: $1 bytes'#000+
'09134_X_Stack space committed: $1 bytes'#000+
- '09200_F_Executable imag','e size is too big for $1 target.'#000+
+ '09200_F_Executable 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+
+ '10001_T_PPU L','oading $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,
+ '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+
+ '10009_U_PPU is compiled for another pro','cessor'#000+
'10010_U_PPU is compiled for another target'#000+
'10011_U_PPU Source: $1'#000+
'10012_U_Writing $1'#000+
- '10','013_F_Can'#039't Write PPU-File'#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+
+ '10017_F_PPU Dbx co','unt problem'#000+
'10018_E_Illegal unit name: $1'#000+
'10019_F_Too much units'#000+
- '10020_F_Circular unit referen','ce between $1 and $2'#000+
+ '10020_F_Circular unit 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+
+ '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 requires the ','-Us switch'#000+
+ '10025_W_Compiling the system unit requires 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+
+ '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 tha','n ppufile'#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+
+ '10033_U_Recompil','ing unit, obj is older than asm'#000+
'10034_U_Parsing interface of $1'#000+
- '10035_U_Parsing implementation',' of $1'#000+
+ '10035_U_Parsing implementation 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+
+ '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 m'+
+ 'ode'#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+
+ '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+
+ '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+
+ '10051_U_Fla','g for reload: $1'#000+
'10052_U_Forced reloading'#000+
'10053_U_Previous state of $1: $2'#000+
- '10054_U_Already com','piling $1, setting second compile'#000+
+ '10054_U_Already 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+
+ '10058_U_Re-resolving un','it $1'#000+
'10059_U_Skipping re-resolving unit $1, still loading used units'#000+
- '10060_U_Unloading resour','ce unit $1 (not needed)'#000+
+ '10060_U_Unloading 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_Indirect int','erface (objects/classes) CRC changed for unit $1'+
- #000+
+ 'ion feedback input ($2, $3); recompile it without wp','o or use the sam'+
+ 'e wpo feedback input file for this compilation invocation'#000+
+ '10062_U_Indirect 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+
+ '11001_W_Only one source file supported, changing sourc','e file to comp'+
+ 'ile from "$1" into "$2"'#000+
'11002_W_DEF file can be created only for OS/2'#000+
- '11003_E_ne','sted response files are not supported'#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+
+ '11006_E_Illegal paramete','r: $1'#000+
'11007_H_-? writes help pages'#000+
'11008_F_Too many config files nested'#000+
- '11009_F_Unable to open',' file $1'#000+
+ '11009_F_Unable 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+
+ '11012_W_Shared libs not supported on DOS platform, reverting',' to stat'+
+ 'ic'#000+
'11013_F_In options file $1 at line $2 too many \var{\#IF(N)DEFs} encou'+
'ntered'#000+
- '11014_','F_In options file $1 at line $2 unexpected \var{\#ENDIFs} enco'+
- 'untered'#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+
+ '11016_W_Debug inform','ation generation is not supported by this execut'+
+ 'able'#000+
'11017_H_Try recompiling with -dGDB'#000+
- '11018_','W_You are using the obsolete switch $1'#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+
+ '11020_N_Switching assembler to default source w','riting assembler'#000+
'11021_W_Assembler output selected "$1" is not compatible with "$2"'#000+
- '11022_W_"$','1" assembler use forced'#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+
+ '11029_O_*** ','press enter ***'#000+
'11030_H_Start of reading config file $1'#000+
- '11031_H_End of reading config file $1'#000,
+ '11031_H_End of reading config 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+
+ '11034_D_Reading config file "$1"',#000+
'11035_D_found source file name "$1"'#000+
'11039_E_Unknown codepage "$1"'#000+
- '11040_F_Config file $1 is a',' directory'#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+
+ '11042_W_Use of ppc386.cfg is deprecated, please u','se fpc.cfg instead'#000+
'11043_F_In options file $1 at line $2 \var{\#ELSE} directive without \'+
- 'var{\','#IF(N)DEF} found'#000+
+ '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 with sma','rt linking on'+
- ' this target, switching to static linking'#000+
+ '11045_F_The feature "$1" is not, or not yet, sup','ported on the select'+
+ 'ed target platform'#000+
+ '11046_N_DWARF debug information cannot be used with smart linking on t'+
+ 'his 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 combination.'#000,
+ '11048_W_Disabling external ','debug information because it is unsupport'+
+ 'ed for the selected target/debug format combination.'#000+
'11049_N_DWARF debug information cannot be used with smart linking with'+
' external assembler, disabling static library creation.'#000+
- '11050_E_Invalid value for MACOSX_DEPLOYMENT_TARGET environment variabl'+
- 'e: $1'#000+
- '11051_E_Invalid value for IPHONEOS_DEP','LOYMENT_TARGET environment var'+
- 'iable: $1'#000+
+ '11050_E_Invalid valu','e for MACOSX_DEPLOYMENT_TARGET environment varia'+
+ 'ble: $1'#000+
+ '11051_E_Invalid value for IPHONEOS_DEPLOYMENT_TARGET environment varia'+
+ 'ble: $1'#000+
'11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when usin'+
'g the EABIHF ABI target'#000+
- '12000_F_Cannot open whole program optimization feedback file "$1"'#000+
- '12001_D_Processing whole program optimiz','ation information in wpo fee'+
- 'dback file "$1"'#000+
+ '12000_F_Cann','ot open whole program optimization feedback file "$1"'#000+
+ '12001_D_Processing whole program optimization information in wpo feedb'+
+ 'ack 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 re','gistered 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 prev','iousl'+
- 'y generated feedback file (use -Fw to specify)'#000+
+ '12003','_E_Expected section header, but got "$2" at line $1 of wpo feed'+
+ 'back file'#000+
+ '12004_W_No handler registered for whole program optimization section "'+
+ '$2" at line $1 of wpo feedback file, ignoring'#000+
+ '12005_D_Found whole program optimization section "$','1" with informati'+
+ 'on about "$2"'#000+
+ '12006_F_The selected whole program optimizations require a previously '+
+ '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',' -FW)'#000+
+ '12','008_F_Specify a whole program optimization feedback file to store '+
+ 'the generated info in (using -FW)'#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_Skip','ping 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',' liveness information from program when'+
- ' stripping symbols, use -Xs-'#000+
+ '12010_E_Not performing any ','whole program optimizations, yet an input'+
+ ' feedback file was specified (using -Fw)'#000+
+ '12011_D_Skipping whole program optimization section "$1", because not '+
+ 'needed by the requested optimizations'#000+
+ '12012_W_Overriding previously read information for',' "$1" from feedbac'+
+ 'k input file using information in section "$2"'#000+
+ '12013_E_Cannot extract symbol liveness information from program when s'+
+ 'tripping symbols, use -Xs-'#000+
'12014_E_Cannot extract symbol liveness information from program when w'+
- 'hen not linking'#000+
+ 'hen not ','linking'#000+
'12015_F_Cannot find "$1" or "$2" to extract symbol liveness informatio'+
- 'n from linked pr','ogram'#000+
+ 'n from linked program'#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 wh','en'+
- ' using smart linking, use -CX -XX'#000+
+ '12017_F_Error executing "$1" (exitcode: $2) to extract symbol info','rm'+
+ 'ation from linked program'#000+
+ '12018_E_Collection of symbol liveness information can only help when u'+
+ 'sing 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-2012 by Florian Klaempfl and othe','rs'#000+
+ '11023_Free Pascal Compiler versi','on $FPCFULLVERSION [$FPCDATE] for $F'+
+ 'PCCPU'#010+
+ 'Copyright (c) 1993-2012 by Florian Klaempfl and others'#000+
'11024_Free Pascal Compiler version $FPCVERSION'#010+
#010+
'Compiler Date : $FPCDATE'#010+
@@ -1152,11 +1148,11 @@ const msgtxt : array[0..000274,1..240] of char=(
'Supported targets:'#010+
' $OSTARGETS'#010+
#010+
- 'Supported CPU instruction sets:'#010+
+ 'Su','pported CPU instruction sets:'#010+
' $INSTRUCTIONSETS'#010+
#010+
'Supported FPU instruction sets:'#010+
- ' $FPUINSTRU','CTIONSETS'#010+
+ ' $FPUINSTRUCTIONSETS'#010+
#010+
'Supported ABI targets:'#010+
' $ABITARGETS'#010+
@@ -1166,228 +1162,228 @@ const msgtxt : array[0..000274,1..240] of char=(
#010+
'Supported Whole Program Optimizations:'#010+
' All'#010+
- ' $WPOPTIMIZATIONS'#010+
+ ' $WPOPTI','MIZATIONS'#010+
#010+
'Supported Microcontroller types:'#010+
' $CONTROLLERTYPES'#010+
#010+
- 'This program comes under the G','NU General Public Licence'#010+
+ 'This program comes under the GNU General Public Licence'#010+
'For more information read COPYING.v2'#010+
#010+
'Please report bugs in our bug tracker on:'#010+
- ' http://bugs.freepascal.org'#010+
+ ' http://bugs.freepascal.','org'#010+
#010+
'More information may be found on our WWW pages (including directions'#010+
- 'for mailing lists us','eful for asking questions or discussing potentia'+
- 'l'#010+
+ 'for mailing lists useful for asking questions or discussing potential'#010+
'new features, etc.):'#010+
' http://www.freepascal.org'#000+
- '11025_**0*_Put + after a boolean switch option to enable it, - to disa'+
- 'ble it'#010+
- '**1a_The compiler doesn'#039't delete the generated as','sembler file'#010+
+ '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 (-dEXTDEBUG compiler)'#010+
- '*L2ap_Use pipes instead of creating temporary assembler files'#010+
- '**2ar_List register allocation/release info in assembler f','ile'#010+
+ '*L2ap_Use pipes instead of',' creating temporary assembler files'#010+
+ '**2ar_List register 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*2Aas_Assemble using GNU A','S'#010+
'3*2Amacho_Mach-O (Darwin, Intel 32 bit) using internal writer'#010+
- '3*2Anasmcoff_COFF (Go32v2) fil','e using Nasm'#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*2Anasmwdosx_Win32/WDOSX object file using Nasm',#010+
'3*2Awasm_Obj file using Wasm (Watcom)'#010+
'3*2Anasmobj_Obj file using Nasm'#010+
- '3*2Amasm_Obj file using',' Masm (Microsoft)'#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+
+ '3*','2Apecoff_PE-COFF (Win32) using internal writer'#010+
'4*2Aas_Assemble using GNU AS'#010+
- '4*2Agas_Assemble u','sing GNU GAS'#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*2Apecoff_PE-COFF (Win64) us','ing internal writer'#010+
'4*2Aelf_ELF (Linux-64bit) using internal writer'#010+
- '6*2Aas_Unix o-file using G','NU AS'#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+
+ 'P*2Aas_Assemble',' using GNU AS'#010+
'S*2Aas_Assemble using GNU AS'#010+
'**1b_Generate browser info'#010+
- '**2bl_Generate local sym','bol 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+
+ '**2Ca<x>_Select ABI, see fpc -','i for possible values'#010+
'**2Cb_Generate big-endian code'#010+
- '**2Cc<x>_Set default calling convention t','o <x>'#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 (de','fault, 32, 64)'+
- #010+
+ '**2Cf<x>_Select fpu instruction set',' to use, see fpc -i for possible '+
+ 'values'#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+
- 'P*2CN_Generate nil-pointer checks (AIX-only)'#010+
+ 'P*2CN_Genera','te nil-pointer checks (AIX-only)'#010+
'**2Co_Check overflow of integer operations'#010+
- '**2CO_Check for po','ssible overflow of integer operations'#010+
+ '**2CO_Check for possible 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+
+ '**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+
+ '**2CR_Verify object method call validity'#010+
'**2Cs<n>_Set stack checking size to <n>'#010+
'**2Ct_Stack checking (for testing only, see manual)'#010+
- 'p*2CT<x>_Target-specific code generation options'#010+
+ 'p*2CT<x>_Target-specifi','c code generation options'#010+
'P*2CT<x>_Target-specific code generation options'#010+
- 'J*2CT<x>_Target-spe','cific code generation options'#010+
+ 'J*2CT<x>_Target-specific code generation options'#010+
'p*3CTsmalltoc_ Generate smaller TOCs at the expense of execution speed'+
' (AIX)'#010+
- 'P*3CTsmalltoc_ Generate smaller TOCs at the expense of execution speed'+
- ' (AIX)'#010+
- 'J*3CTcompactintarrayinit_ Generate smaller (but potentia','lly slower) '+
- 'code for initializing integer array constants'#010+
+ 'P*3CTsmalltoc_ Generate smaller TOCs at',' the expense of execution spe'+
+ 'ed (AIX)'#010+
+ 'J*3CTcompactintarrayinit_ Generate smaller (but potentially slower) co'+
+ 'de for initializing integer array constants'#010+
+ 'K*3CTenumfieldinit_ Initialize enumeration fields in constructors to e'+
+ 'numtype(0), after ','calling inherited constructors'#010+
'J*2Cv_Var/out parameter copy-out checking'#010+
'**2CX_Create also smartlinked library'#010+
'**1d<x>_Defines the symbol <x>'#010+
'**1D_Generate a DEF file'#010+
'**2Dd<x>_Set description to <x>'#010+
- '**2Dv<x>_Set D','LL version to <x>'#010+
- '*O2Dw_PM application'#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 codepa','ge to <x>'#010+
- '**2FC<x>_Set RC compiler binary name to <x>'#010+
+ '**2Fc<x>_Set input codepage to <x>'#010+
+ '**2FC<x>_Set RC c','ompiler 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 framewor','k path (Darwin only)'#010+
- '**2FE<x>_Set exe/unit output path 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 di'+
'r'#010+
- '**2Fo','<x>_Add <x> to object path'#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 whole-program optimization',' feedback in <x>'#010+
- '**2Fw<x>_Load previously stored whole-program optimization feedback fr'+
- 'om <x>'#010+
+ '**2FW<x>_Store generated whole-program optimization feedback in <x>'#010+
+ '**2Fw<x>_L','oad previously stored whole-program optimization feedback '+
+ 'from <x>'#010+
'*g1g_Generate debug information (default format for target)'#010+
'*g2gc_Generate checks for pointers'#010+
- '*g2gh_Use heaptrace unit (for memory leak/corruptio','n debugging)'#010+
- '*g2gl_Use line info unit (show more info with backtraces)'#010+
+ '*g2gh_Use heaptrace unit (for 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 absolute/full include fi','le paths in Sta'+
- 'bs'#010+
- '*g3godwarfmethodclassprefix_ Prefix method names in DWARF with class n'+
- 'ame'#010+
+ '*g3gostabsabsincludes_ Store absolute/full include file paths in Stabs'+
+ #010+
+ '*g3godwar','fmethodclassprefix_ Prefix method names in DWARF with class'+
+ ' name'#010+
'*g2gp_Preserve case in stabs symbol names'#010+
'*g2gs_Generate Stabs debug information'#010+
'*g2gt_Trash local variables (to detect uninitialized uses)'#010+
- '*g2gv_Ge','nerates programs traceable with Valgrind'#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 information (experimental)'#010+
- '**','1i_Information'#010+
- '**2iD_Return compiler date'#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 target processor'#010+
- '**1I<x>_','Add <x> to include path'#010+
- '**1k<x>_Pass <x> to the linker'#010+
+ '**1I<x>_Add <x> to include path'#010+
+ '**1','k<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 compatibility mode'#010+
- '**2Mtp_TP/BP',' 7.0 compatibility mode'#010+
- '**2Mmacpas_Macintosh Pascal dialects compatibility mode'#010+
+ '**2Mtp_TP/BP 7.0 compatibility mode'#010+
+ '**2','Mmacpas_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 produced to <x>'#010+
- '**1O<x>_O','ptimizations:'#010+
- '**2O-_Disable optimizations'#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 possibl'+
+ '**2Oo[NO]<x>_Enable or disabl','e optimizations, see fpc -i for possibl'+
'e 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 pos','sible values'#010+
- '**2Ow<x>_Perform whole-program optimization <x>, see fpc -i for possib'+
- 'le values'#010+
+ ' <x>, see fpc -i for possible values'#010+
+ '**2Ow<x>_Perfo','rm whole-program optimization <x>, see fpc -i for poss'+
+ 'ible values'#010+
'**2Os_Optimize for size rather than speed'#010+
'**1pg_Generate profile code for gprof (defines FPC_PROFILE)'#010+
- 'F*1P<x>_Target CPU / compiler related options',':'#010+
- 'F*2PB_Show default compiler binary'#010+
+ 'F*1P<x>_Target CPU / compiler related options:'#010+
+ 'F*2PB_Show default compil','er binary'#010+
'F*2PP_Show default target cpu'#010+
'F*2P<x>_Set target CPU (arm,i386,m68k,mips,mipsel,powerpc,powerpc64,sp'+
'arc,x86_64'#010+
'**1R<x>_Assembler reading style:'#010+
'**2Rdefault_Use default assembler for target'#010+
- '3*2Ratt_Read A','T&T style assembler'#010+
- '3*2Rintel_Read Intel style assembler'#010+
+ '3*2Ratt_Read AT&T style assembler'#010+
+ '3*2Rint','el_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+
+ '**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 af','ter hints'#010+
- '**2Sg_Enable LABEL and GOTO (default in -Mtp and -Mdelphi)'#010+
+ '**3*_h : Compiler also halts after hints'#010+
+ '**2Sg_Enable LABE','L and GOTO (default in -Mtp and -Mdelphi)'#010+
'**2Sh_Use reference counted strings (ansistring by default) instead of'+
' shortstrings'#010+
'**2Si_Turn on inlining of procedures/functions declared as "inline"'#010+
- '**2Sk_Load fpcylix ','unit'#010+
- '**2SI<x>_Set interface style to <x>'#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+
+ '**2Ss_Constructor name must be init (destructor must be done)'#010+
+ '**2Sx_Enable exception key','words (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+
- '**2s','r_Skip register allocation phase (use with -alr)'#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: -T'+
+ '3*2Tiphonesim_ iPhoneSimulator from iOS ','SDK 3.2+ (older versions: -T'+
'darwin)'#010+
'3*2Tlinux_Linux'#010+
'3*2Tnetbsd_NetBSD'#010+
@@ -1395,8 +1391,8 @@ const msgtxt : array[0..000274,1..240] of char=(
'3*2Tnetwlibc_Novell Netware Module (libc)'#010+
'3*2Topenbsd_OpenBSD'#010+
'3*2Tos2_OS/2 / eComStation'#010+
- '3*2Tsunos_Sun','OS/Solaris'#010+
- '3*2Tsymbian_Symbian OS'#010+
+ '3*2Tsunos_SunOS/Solaris'#010+
+ '3*2Tsymbian_Symb','ian OS'#010+
'3*2Tsolaris_Solaris'#010+
'3*2Twatcom_Watcom compatible DOS extender'#010+
'3*2Twdosx_WDOSX DOS extender'#010+
@@ -1404,8 +1400,8 @@ const msgtxt : array[0..000274,1..240] of char=(
'3*2Twince_Windows CE'#010+
'4*2Tdarwin_Darwin/Mac OS X'#010+
'4*2Tlinux_Linux'#010+
- '4*2Twin64_Win64 (64 bit Wi','ndows systems)'#010+
- '6*2Tamiga_Commodore Amiga'#010+
+ '4*2Twin64_Win64 (64 bit Windows systems)'#010+
+ '6*2Tamiga_Co','mmodore Amiga'#010+
'6*2Tatari_Atari ST/STe/TT'#010+
'6*2Tlinux_Linux'#010+
'6*2Tpalmos_PalmOS'#010+
@@ -1415,118 +1411,118 @@ const msgtxt : array[0..000274,1..240] of char=(
'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+
+ 'P*2Tmacos_Mac OS (classic)'#010+
+ 'P*2Tmorpho','s_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_Generate release unit files (never automatically',' recompiled)'#010+
- '**2Us_Compile a system unit'#010+
+ '**2Ur_Generate 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 warnings u : Show unit info'#010+
- '**2*_n',' : Show notes t : Show tried/used files'#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 linenumbers r : Rhide/GCC compatibility mo','d'+
- 'e'#010+
- '**2*_s : Show time stamps q : Show message numbers'#010+
+ '**2*_l : Show linenumbers r : Rhide/GCC compatibility mode'#010+
+ '**2*_s : Show time stamp','s 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 parse tre'+
'e'#010+
- '**2*_ with full path ',' v : Write fpcdebug.txt with'#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+
'F*1V<x>_Append '#039'-<x>'#039' to the used compiler binary name (e.g. f'+
'or version)'#010+
- '**1W<x>_Targe','t-specific options (targets)'#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 (Darwin)'#010+
+ 'P*2Wb_Create a bundle instead of a library',' (Darwin)'#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, Symb','ian)'#010+
- '3*2WBxxxx_Set image base to xxxx (Windows, Symbian)'#010+
+ '3*2WB_Create a relocatable image (Windows, Symbian)'#010+
+ '3*2WBxxxx_Set image ba','se to 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, Sy','mbian)'#010+
- '3*2WC_Specify console type application (EMX, OS/2, Windows)'#010+
+ 'A*2WBxxxx_Set image base to xxxx (Windows, Symbian)'#010+
+ '3*2WC_Specify consol','e type 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_Us','e DEFFILE to export functions of DLL or EXE (Windows)'#010+
+ '3*2WD_Use DEFFILE to export functio','ns of 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 resou','rces (Darwin)'#010+
- 'A*2We_Use external resources (Darwin)'#010+
+ '4*2We_Use external resources (Darwin)'#010+
+ 'A*2We_Use ext','ernal 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, Window','s)'#010+
- '4*2WG_Specify graphic type application (EMX, OS/2, Windows)'#010+
+ '3*2WG_Specify graphic type application (EMX, OS/2, Windows)'#010+
+ '4*2WG_Specify graphic ty','pe application (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 (Darw','in)'#010+
- 'A*2Wi_Use internal resources (Darwin)'#010+
+ '4*2Wi_Use internal resources (Darwin)'#010+
+ 'A*2Wi_Use internal reso','urces (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_Tu','rn on/off the usage of import sections (Windows)'#010+
+ 'A*2WI_Turn on/off the usage of impo','rt sections (Windows)'#010+
'3*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
'n)'#010+
'4*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
'n)'#010+
- 'p*2WM<x>_Minimum Mac OS X deployment version:',' 10.4, 10.5.1, ... (Dar'+
- 'win)'#010+
+ 'p*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
+ 'n)',#010+
'P*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
'n)'#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+
+ '4*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
+ 'A*2WN_Do not generate relo','cation code, needed for debugging (Windows'+
+ ')'#010+
'A*2Wpxxxx_Specify the controller type, see fpc -i for possible values'#010+
'V*2Wpxxxx_Specify the controller type, see fpc -i for possible values'#010+
- '3*2WP<x>_Minimum iOS deployme','nt version: 3.0, 5.0.1, ... (iphonesim)'+
+ '3*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ...',' (iphonesim)'+
#010+
'A*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (Darwin)'#010+
'3*2WR_Generate relocation code (Windows)'#010+
'4*2WR_Generate relocation code (Windows)'#010+
'A*2WR_Generate relocation code (Windows)'#010+
- 'P*2WT_Speci','fy MPW tool type application (Classic Mac OS)'#010+
+ 'P*2WT_Specify MPW tool type applicatio','n (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 search default library path (sometimes requi','red for cro'+
- 'ss-compiling when not using -XR)'#010+
+ '**2Xd_Do not search default library path (sometimes required for cross'+
+ '-compiling whe','n not using -XR)'#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',' linker'#010+
- '**2Xm_Generate link map'#010+
+ '**2Xi_Use internal linker'#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+
'F*2Xp<x>_First search for the compiler binary in the directory <x>'#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 co'+
+ '**2Xr<x>_Set the linker'#039's rlink-path to ','<x> (needed for cross co'+
'mpile, see the ld manual 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 exe','cutable'#010+
- '**2XS_Try to link units statically (default, defines FPC_LINK_STATIC)'#010+
+ '**2Xs_Strip all symbols from executable'#010+
+ '**2XS_Try to link u','nits statically (default, defines FPC_LINK_STATIC'+
+ ')'#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_Sh','ows this help without waiting'
+ '**1h_Shows this help without waiti','ng'
);
diff --git a/mips/compiler/nbas.pas b/mips/compiler/nbas.pas
index 2fe6b2db69..608b783862 100644
--- a/mips/compiler/nbas.pas
+++ b/mips/compiler/nbas.pas
@@ -1201,7 +1201,7 @@ implementation
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));
+ tempinfo^.typedef.GetTypeName,'", temptype = ',tempinfo^.temptype,', tempinfo = $',hexstr(ptrint(tempinfo),sizeof(ptrint)*2));
end;
end.
diff --git a/mips/compiler/ncgcal.pas b/mips/compiler/ncgcal.pas
index 7055b9d2b4..2bb4b6d15b 100644
--- a/mips/compiler/ncgcal.pas
+++ b/mips/compiler/ncgcal.pas
@@ -133,7 +133,7 @@ implementation
begin
if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
internalerror(200304235);
- hlcg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,left.resultdef,tempcgpara.def,left.location.reference,tempcgpara);
+ hlcg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location.reference,tempcgpara);
end;
@@ -203,8 +203,8 @@ implementation
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');
+ hlcg.g_array_rtti_helper(current_asmdata.CurrAsmList,tarraydef(resultdef).elementdef,
+ href,third.location,'fpc_finalize_array');
end;
end
else
@@ -529,7 +529,9 @@ implementation
passing a shortstring }
if (hp2.nodetype=typeconvn) and
(tunarynode(hp2).left.nodetype=addrn) then
- hp2:=tunarynode(tunarynode(hp2).left).left;
+ hp2:=tunarynode(tunarynode(hp2).left).left
+ else if tunarynode(hp2).nodetype=addrn then
+ hp2:=tunarynode(hp2).left;
location_freetemp(current_asmdata.CurrAsmList,hp2.location);
hp:=tarrayconstructornode(hp).right;
end;
@@ -833,9 +835,9 @@ implementation
{ call method }
extra_call_code;
{$ifdef x86}
- cg.a_call_ref(current_asmdata.CurrAsmList,href);
+ hlcg.a_call_ref(current_asmdata.CurrAsmList,tabstractprocdef(procdefinition),href);
{$else x86}
- cg.a_call_reg(current_asmdata.CurrAsmList,pvreg);
+ hlcg.a_call_reg(current_asmdata.CurrAsmList,tabstractprocdef(procdefinition),pvreg);
{$endif x86}
extra_post_call_code;
end
@@ -911,7 +913,7 @@ implementation
if (po_interrupt in procdefinition.procoptions) then
extra_interrupt_code;
extra_call_code;
- cg.a_call_reg(current_asmdata.CurrAsmList,pvreg);
+ hlcg.a_call_reg(current_asmdata.CurrAsmList,tabstractprocdef(procdefinition),pvreg);
extra_post_call_code;
end;
@@ -971,7 +973,7 @@ implementation
(tf_safecall_exceptions in target_info.flags) then
begin
cgpara.init;
- paramanager.getintparaloc(pocall_default,1,cgpara);
+ paramanager.getintparaloc(pocall_default,1,s32inttype,cgpara);
cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_INT,NR_FUNCTION_RESULT_REG,cgpara);
paramanager.freecgpara(current_asmdata.CurrAsmList,cgpara);
cgpara.done;
diff --git a/mips/compiler/ncgflw.pas b/mips/compiler/ncgflw.pas
index bc01ed5c6d..10aa87c691 100644
--- a/mips/compiler/ncgflw.pas
+++ b/mips/compiler/ncgflw.pas
@@ -93,7 +93,7 @@ implementation
uses
verbose,globals,systems,globtype,constexp,
- symconst,symdef,symsym,aasmtai,aasmdata,aasmcpu,defutil,
+ symconst,symdef,symsym,symtable,aasmtai,aasmdata,aasmcpu,defutil,
procinfo,cgbase,pass_2,parabase,
cpubase,cpuinfo,
nld,ncon,
@@ -962,16 +962,17 @@ implementation
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
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,class_tobject,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,voidpointertype,paraloc3);
+
{ multiple parameters? }
if assigned(right) then
begin
@@ -991,7 +992,7 @@ implementation
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);
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3);
{ push address }
cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
end
@@ -1007,7 +1008,7 @@ implementation
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);
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2);
end;
cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
@@ -1016,6 +1017,10 @@ implementation
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RAISEEXCEPTION',false);
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
end
else
begin
@@ -1024,9 +1029,6 @@ implementation
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
end;
- paraloc1.done;
- paraloc2.done;
- paraloc3.done;
end;
@@ -1330,7 +1332,7 @@ implementation
{ send the vmt parameter }
reference_reset_symbol(href2,current_asmdata.RefAsmSymbol(excepttype.vmt_mangledname),0,sizeof(pint));
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,search_system_type('TCLASS').typedef,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');
@@ -1446,7 +1448,7 @@ implementation
{ call fpc_safecallhandler, passing self for methods of classes,
nil otherwise. }
cgpara.init;
- paramanager.getintparaloc(pocall_default,1,cgpara);
+ paramanager.getintparaloc(pocall_default,1,class_tobject,cgpara);
if is_class(current_procinfo.procdef.struct) then
begin
selfsym:=tparavarsym(current_procinfo.procdef.parast.Find('self'));
diff --git a/mips/compiler/ncginl.pas b/mips/compiler/ncginl.pas
index cfdcb480f4..98265cf399 100644
--- a/mips/compiler/ncginl.pas
+++ b/mips/compiler/ncginl.pas
@@ -54,8 +54,7 @@ interface
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_rox_sar; virtual;
procedure second_bsfbsr; virtual;
procedure second_new; virtual;
procedure second_setlength; virtual; abstract;
@@ -168,11 +167,10 @@ implementation
in_rol_x,
in_rol_x_y,
in_ror_x,
- in_ror_x_y:
- second_rox;
+ in_ror_x_y,
in_sar_x,
in_sar_x_y:
- second_sar;
+ second_rox_sar;
in_bsf_x,
in_bsr_x:
second_BsfBsr;
@@ -204,10 +202,10 @@ implementation
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);
+ paramanager.getintparaloc(pocall_default,1,getpointerdef(cshortstringtype),paraloc1);
+ paramanager.getintparaloc(pocall_default,2,getpointerdef(cshortstringtype),paraloc2);
+ paramanager.getintparaloc(pocall_default,3,s32inttype,paraloc3);
+ paramanager.getintparaloc(pocall_default,4,voidpointertype,paraloc4);
otlabel:=current_procinfo.CurrTrueLabel;
oflabel:=current_procinfo.CurrFalseLabel;
current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
@@ -231,7 +229,7 @@ implementation
{ 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);
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,current_filepos.line,paraloc3);
{ push filename }
cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,hp2.location.reference,paraloc2);
{ push msg }
@@ -721,10 +719,9 @@ implementation
end;
- procedure tcginlinenode.second_rox;
+ procedure tcginlinenode.second_rox_sar;
var
op : topcg;
- {hcountreg : tregister;}
op1,op2 : tnode;
begin
{ one or two parameters? }
@@ -733,13 +730,15 @@ implementation
begin
op1:=tcallparanode(tcallparanode(left).right).left;
op2:=tcallparanode(left).left;
+ secondpass(op2);
end
else
- op1:=left;
+ begin
+ op1:=left;
+ op2:=nil;
+ end;
secondpass(op1);
- { load left operator in a register }
- location_copy(location,op1.location);
case inlinenumber of
in_ror_x,
in_ror_x_y:
@@ -747,66 +746,35 @@ implementation
in_rol_x,
in_rol_x_y:
op:=OP_ROL;
+ in_sar_x,
+ in_sar_x_y:
+ op:=OP_SAR;
end;
- hlcg.location_force_reg(current_asmdata.CurrAsmList,location,op1.resultdef,resultdef,false);
- if (left.nodetype=callparan) and
- assigned(tcallparanode(left).right) then
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,op1.location,op1.resultdef,resultdef,true);
+
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+
+ if assigned(op2) 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)
+ hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,
+ tordconstnode(op2).value.uvalue and (resultdef.size*8-1),
+ op1.location.register, location.register)
else
begin
- hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,op2.resultdef,resultdef,false);
- { do modulo 2 operation }
- cg.a_op_reg_reg(current_asmdata.CurrAsmList,op,location.size,op2.location.register,location.register);
+ hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,
+ op2.resultdef,resultdef,true);
+ hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,resultdef,
+ op2.location.register,op1.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);
-
- hlcg.location_force_reg(current_asmdata.CurrAsmList,location,op1.resultdef,resultdef,false);
-
- if not(assigned(op2)) then
- hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,resultdef,1,location.register)
- else
- begin
- secondpass(op2);
- { shifting by a constant directly coded: }
- if op2.nodetype=ordconstn then
- hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,resultdef,
- tordconstnode(op2).value.uvalue and (resultdef.size*8-1),location.register)
- else
- begin
- hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,op2.resultdef,resultdef,false);
- hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SAR,resultdef,op2.location.register,location.register);
- end;
- end;
+ hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,1,
+ op1.location.register,location.register);
end;
diff --git a/mips/compiler/ncgld.pas b/mips/compiler/ncgld.pas
index cc9f342745..9c7636fe8f 100644
--- a/mips/compiler/ncgld.pas
+++ b/mips/compiler/ncgld.pas
@@ -362,7 +362,7 @@ implementation
current_asmdata.getjumplabel(endrelocatelab);
{ make sure hregister can't allocate the register necessary for the parameter }
paraloc1.init;
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,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);
diff --git a/mips/compiler/ncgmat.pas b/mips/compiler/ncgmat.pas
index fcc0a57e0e..5d733754ee 100644
--- a/mips/compiler/ncgmat.pas
+++ b/mips/compiler/ncgmat.pas
@@ -380,7 +380,7 @@ implementation
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);
+ paramanager.getintparaloc(pocall_default,1,s32inttype,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);
diff --git a/mips/compiler/ncgmem.pas b/mips/compiler/ncgmem.pas
index 86cfd7dc45..ae4256c356 100644
--- a/mips/compiler/ncgmem.pas
+++ b/mips/compiler/ncgmem.pas
@@ -263,7 +263,7 @@ implementation
(location.reference.base<>NR_NO) then
begin
paraloc1.init;
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,paraloc1);
cg.a_load_reg_cgpara(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
paraloc1.done;
@@ -332,7 +332,7 @@ implementation
(cs_checkpointer in current_settings.localswitches) and
not(cs_compilesystem in current_settings.moduleswitches) then
begin
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,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);
@@ -674,8 +674,8 @@ implementation
else
if is_dynamic_array(left.resultdef) then
begin
- paramanager.getintparaloc(pocall_default,1,paraloc1);
- paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,search_system_type('TDYNARRAYINDEX').typedef,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);
@@ -704,8 +704,8 @@ implementation
st_widestring,
st_ansistring:
begin
- paramanager.getintparaloc(pocall_default,1,paraloc1);
- paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,ptrsinttype,paraloc2);
cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
diff --git a/mips/compiler/ncgopt.pas b/mips/compiler/ncgopt.pas
index 9cb314688c..8037d070de 100644
--- a/mips/compiler/ncgopt.pas
+++ b/mips/compiler/ncgopt.pas
@@ -43,7 +43,7 @@ uses
aasmbase,aasmtai,aasmdata,
ncnv, ncon, pass_2,
cgbase, cpubase,
- tgobj, cgobj, cgutils,ncgutil;
+ tgobj, cgobj, hlcgobj, cgutils,ncgutil;
{*****************************************************************************
@@ -91,7 +91,7 @@ begin
(tg.sizeoftemp(current_asmdata.CurrAsmList,left.location.reference) = 256)) then
begin
tg.gethltemp(current_asmdata.CurrAsmList,cshortstringtype,256,tt_normal,href);
- cg.g_copyshortstring(current_asmdata.CurrAsmList,left.location.reference,href,255);
+ hlcg.g_copyshortstring(current_asmdata.CurrAsmList,left.location.reference,href,tstringdef(cshortstringtype));
location_freetemp(current_asmdata.CurrAsmList,left.location);
{ return temp reference }
location_reset_ref(left.location,LOC_REFERENCE,def_cgsize(resultdef),1);
diff --git a/mips/compiler/ncgutil.pas b/mips/compiler/ncgutil.pas
index 49d935ed28..7f30449866 100644
--- a/mips/compiler/ncgutil.pas
+++ b/mips/compiler/ncgutil.pas
@@ -417,9 +417,9 @@ implementation
paraloc1.init;
paraloc2.init;
paraloc3.init;
- paramanager.getintparaloc(pocall_default,1,paraloc1);
- paramanager.getintparaloc(pocall_default,2,paraloc2);
- paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.getintparaloc(pocall_default,1,s32inttype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,voidpointertype,paraloc3);
cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3);
cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2);
{ push type of exceptionframe }
@@ -431,7 +431,7 @@ implementation
cg.a_call_name(list,'FPC_PUSHEXCEPTADDR',false);
cg.deallocallcpuregisters(list);
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,search_system_type('PJMP_BUF').typedef,paraloc1);
cg.a_load_reg_cgpara(list,OS_ADDR,NR_FUNCTION_RESULT_REG,paraloc1);
paramanager.freecgpara(list,paraloc1);
cg.allocallcpuregisters(list);
@@ -681,7 +681,7 @@ implementation
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)
+ hlcg.g_copyshortstring(list,href,localcopyloc.reference,tstringdef(tparavarsym(p).vardef));
end
else if tparavarsym(p).vardef.typ = variantdef then
begin
@@ -689,7 +689,7 @@ implementation
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)
+ hlcg.g_copyvariant(list,href,localcopyloc.reference,tvariantdef(tparavarsym(p).vardef))
end
else
begin
@@ -739,10 +739,10 @@ implementation
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');
+ hlcg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'fpc_addref_array');
end
else
- cg.g_incrrefcount(list,tparavarsym(p).vardef,href);
+ hlcg.g_incrrefcount(list,tparavarsym(p).vardef,href);
end;
end;
vs_out :
@@ -757,10 +757,10 @@ implementation
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');
+ hlcg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'fpc_initialize_array');
end
else
- cg.g_initialize(list,tparavarsym(p).vardef,href);
+ hlcg.g_initialize(list,tparavarsym(p).vardef,href);
end;
end;
end;
@@ -1310,7 +1310,7 @@ implementation
paraloc1 : tcgpara;
begin
paraloc1.init;
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,ptruinttype,paraloc1);
cg.a_load_const_cgpara(list,OS_INT,current_procinfo.calc_stackframe_size,paraloc1);
paramanager.freecgpara(list,paraloc1);
paraloc1.done;
@@ -1323,7 +1323,7 @@ implementation
begin
paraloc1.init;
{ Also alloc the register needed for the parameter }
- paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,1,ptruinttype,paraloc1);
paramanager.freecgpara(list,paraloc1);
{ Call the helper }
cg.allocallcpuregisters(list);
diff --git a/mips/compiler/ncnv.pas b/mips/compiler/ncnv.pas
index 3ed3576867..db1baaf72f 100644
--- a/mips/compiler/ncnv.pas
+++ b/mips/compiler/ncnv.pas
@@ -134,6 +134,7 @@ interface
function first_cstring_to_int : tnode;virtual;
function first_string_to_chararray : tnode;virtual;
function first_char_to_string : tnode;virtual;
+ function first_char_to_chararray : tnode; virtual;
function first_nothing : tnode;virtual;
function first_array_to_pointer : tnode;virtual;
function first_int_to_real : tnode;virtual;
@@ -163,6 +164,7 @@ interface
function _first_cstring_to_int : tnode;
function _first_string_to_chararray : tnode;
function _first_char_to_string : tnode;
+ function _first_char_to_chararray : tnode;
function _first_nothing : tnode;
function _first_array_to_pointer : tnode;
function _first_int_to_real : tnode;
@@ -1277,16 +1279,7 @@ implementation
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;
+ result:=nil;
end;
@@ -2825,6 +2818,22 @@ implementation
end;
+ function ttypeconvnode.first_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.first_nothing : tnode;
begin
first_nothing:=nil;
@@ -3334,6 +3343,11 @@ implementation
result:=first_char_to_string;
end;
+ function ttypeconvnode._first_char_to_chararray: tnode;
+ begin
+ result:=first_char_to_chararray;
+ end;
+
function ttypeconvnode._first_nothing : tnode;
begin
result:=first_nothing;
@@ -3433,7 +3447,7 @@ implementation
@ttypeconvnode._first_nothing, {not_possible}
@ttypeconvnode._first_string_to_string,
@ttypeconvnode._first_char_to_string,
- @ttypeconvnode._first_nothing, { char_2_chararray, needs nothing extra }
+ @ttypeconvnode._first_char_to_chararray,
nil, { removed in typecheck_chararray_to_string }
@ttypeconvnode._first_cchar_to_pchar,
@ttypeconvnode._first_cstring_to_pchar,
diff --git a/mips/compiler/nobj.pas b/mips/compiler/nobj.pas
index 837421c188..b78ce2aa05 100644
--- a/mips/compiler/nobj.pas
+++ b/mips/compiler/nobj.pas
@@ -416,7 +416,12 @@ implementation
{ 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),
+{$ifdef jvm}
+ MessagePos4(pd.fileinfo,parser_e_method_lower_visibility,
+{$else jvm}
+ MessagePos4(pd.fileinfo,parser_n_ignore_lower_visibility,
+{$endif jvm}
+ pd.fullprocname(false),
visibilityname[pd.visibility],tobjectdef(vmtpd.owner.defowner).objrealname^,visibilityname[vmtentryvis])
else if pd.visibility>vmtentryvis then
begin
diff --git a/mips/compiler/ogbase.pas b/mips/compiler/ogbase.pas
index 0833088a02..08b3a01fcf 100644
--- a/mips/compiler/ogbase.pas
+++ b/mips/compiler/ogbase.pas
@@ -42,6 +42,7 @@ interface
TExeSection = class;
TExeSymbol = class;
+ TExeOutput = class;
TObjRelocationType = (
{ Relocation to absolute address }
@@ -119,11 +120,7 @@ interface
oso_Data,
{ Is loaded into memory }
oso_load,
- { Not loaded into memory }
- oso_noload,
- { Read only }
- oso_readonly,
- { Read/Write }
+ { Writable }
oso_write,
{ Contains executable instructions }
oso_executable,
@@ -172,10 +169,12 @@ interface
TObjRelocation = class
DataOffset,
- orgsize : aword; { original size of the symbol to Relocate, required for COFF }
+ orgsize : aword; { COFF: original size of the symbol to relocate }
+ { ELF: explicit addend }
symbol : TObjSymbol;
objsection : TObjSection; { only used if symbol=nil }
typ : TObjRelocationType;
+ size : byte;
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);
@@ -189,6 +188,7 @@ interface
procedure SetSecOptions(Aoptions:TObjSectionOptions);
public
ObjData : TObjData;
+ index : longword; { index of section in section headers }
SecSymIdx : longint; { index for the section in symtab }
SecAlign : shortint; { alignment of the section }
{ section Data }
@@ -198,8 +198,6 @@ interface
DataAlignBytes : shortint;
{ Relocations (=references) to other sections }
ObjRelocations : TFPObjectList;
- { Symbols this defines }
- ObjSymbolDefines : TFPObjectList;
{ executable linking }
ExeSection : TExeSection;
USed : Boolean;
@@ -214,8 +212,7 @@ interface
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 FixupRelocs(Exe: TExeOutput);virtual;
procedure ReleaseData;
function FullName:string;
property Data:TDynamicArray read FData;
@@ -244,7 +241,6 @@ interface
property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
public
CurrPass : byte;
- ImageBase : aword;
constructor create(const n:string);virtual;
destructor destroy;override;
{ Sections }
@@ -350,7 +346,6 @@ interface
TExeSymbol = class(TFPHashObject)
ObjSymbol : TObjSymbol;
- ExeSection : TExeSection;
State : TSymbolState;
{ Used for vmt references optimization }
VTable : TExeVTable;
@@ -368,7 +363,7 @@ interface
SecOptions : TObjSectionOptions;
constructor create(AList:TFPHashObjectList;const AName:string);virtual;
destructor destroy;override;
- procedure AddObjSection(objsec:TObjSection);
+ procedure AddObjSection(objsec:TObjSection);virtual;
property ObjSectionList:TFPObjectList read FObjSectionList;
property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
end;
@@ -422,6 +417,7 @@ interface
FUnresolvedExeSymbols : TFPObjectList;
FExternalObjSymbols,
FCommonObjSymbols : TFPObjectList;
+ FProvidedObjSymbols : TFPObjectList;
FEntryName : string;
FExeVTableList : TFPObjectList;
{ Objects }
@@ -470,10 +466,12 @@ interface
procedure Order_ObjSection(const aname:string);virtual;
procedure MemPos_Start;virtual;
procedure MemPos_Header;virtual;
+ procedure MemPos_ExeSection(exesec:TExeSection);
procedure MemPos_ExeSection(const aname:string);virtual;
procedure MemPos_EndExeSection;virtual;
procedure DataPos_Start;virtual;
procedure DataPos_Header;virtual;
+ procedure DataPos_ExeSection(exesec:TExeSection);
procedure DataPos_ExeSection(const aname:string);virtual;
procedure DataPos_EndExeSection;virtual;
procedure DataPos_Symbols;virtual;
@@ -483,6 +481,7 @@ interface
procedure PrintMemoryMap;
procedure FixupSymbols;
procedure FixupRelocations;
+ procedure RemoveUnusedExeSymbols;
procedure MergeStabs;
procedure RemoveUnreferencedSections;
procedure RemoveEmptySections;
@@ -644,7 +643,6 @@ implementation
secsymidx:=0;
{ relocation }
ObjRelocations:=TFPObjectList.Create(true);
- ObjSymbolDefines:=TFPObjectList.Create(false);
VTRefList:=TFPObjectList.Create(false);
end;
@@ -655,7 +653,6 @@ implementation
Data.Free;
stringdispose(FCachedFullName);
ObjRelocations.Free;
- ObjSymbolDefines.Free;
VTRefList.Free;
inherited destroy;
end;
@@ -748,15 +745,7 @@ implementation
end;
- procedure TObjSection.AddSymbolDefine(p:TObjSymbol);
- begin
- if p.bind<>AB_GLOBAL then
- exit;
- ObjSymbolDefines.Add(p);
- end;
-
-
- procedure TObjSection.FixupRelocs;
+ procedure TObjSection.FixupRelocs(Exe:TExeOutput);
begin
end;
@@ -770,8 +759,6 @@ implementation
end;
ObjRelocations.free;
ObjRelocations:=nil;
- ObjSymbolDefines.Free;
- ObjSymbolDefines:=nil;
if assigned(FCachedFullName) then
begin
stringdispose(FCachedFullName);
@@ -918,7 +905,7 @@ implementation
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],
+ {code} [oso_Data,oso_load,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],
@@ -930,29 +917,29 @@ implementation
,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],
+ {pdata} [oso_data,oso_load {$ifndef x86_64},oso_keep{$endif}],
+ {stub} [oso_Data,oso_load,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],
+ {stab} [oso_Data,oso_debug],
+ {stabstr} [oso_Data,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],
+ {eData} [oso_Data,oso_load],
+ {eh_frame} [oso_Data,oso_load],
+ {debug_frame} [oso_Data,oso_debug],
+ {debug_info} [oso_Data,oso_debug],
+ {debug_line} [oso_Data,oso_debug],
+ {debug_abbrev} [oso_Data,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],
+ {toc} [oso_Data,oso_load],
+ {init} [oso_Data,oso_load,oso_executable,oso_keep],
+ {fini} [oso_Data,oso_load,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],
@@ -1078,8 +1065,6 @@ implementation
begin
result:=TObjSymbol(asmsym.cachedObjSymbol);
result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
- { Register also in TObjSection }
- CurrObjSec.AddSymbolDefine(result);
end;
end
else
@@ -1092,8 +1077,6 @@ implementation
if not assigned(CurrObjSec) then
internalerror(200603051);
result:=CreateSymbol(aname);
- { Register also in TObjSection }
- CurrObjSec.AddSymbolDefine(result);
result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
end;
@@ -1551,6 +1534,7 @@ implementation
FUnresolvedExeSymbols:=TFPObjectList.Create(false);
FExternalObjSymbols:=TFPObjectList.Create(false);
FCommonObjSymbols:=TFPObjectList.Create(false);
+ FProvidedObjSymbols:=TFPObjectList.Create(false);
FExeVTableList:=TFPObjectList.Create(false);
FEntryName:='start';
{ sections }
@@ -1573,6 +1557,7 @@ implementation
FExeSymbolList.free;
UnresolvedExeSymbols.free;
ExternalObjSymbols.free;
+ FProvidedObjSymbols.free;
CommonObjSymbols.free;
ExeVTableList.free;
FExeSectionList.free;
@@ -1659,7 +1644,7 @@ implementation
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);
+ objsym:=internalObjData.SymbolDefine('__image_base__',AB_GLOBAL,AT_DATA);
exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
exesym.ObjSymbol:=objsym;
end;
@@ -1668,7 +1653,7 @@ implementation
procedure TExeOutput.Load_Symbol(const aname:string);
begin
internalObjData.createsection('*'+aname,0,[]);
- internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION);
+ internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_DATA);
end;
procedure TExeOutput.Load_ProvideSymbol(const aname:string);
@@ -1763,13 +1748,17 @@ implementation
procedure TExeOutput.Order_ProvideSymbol(const aname:string);
var
ObjSection : TObjSection;
+ exesym : TExeSymbol;
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
+ exesym:=TExeSymbol(ExeSymbolList.Find(aname));
+ if not assigned(exesym) then
+ internalerror(201206301);
+ { Only include this section if it actually resolves
+ the symbol }
+ if exesym.objsymbol.objsection=objsection then
CurrExeSec.AddObjSection(ObjSection);
end;
@@ -1912,29 +1901,35 @@ implementation
end;
- procedure TExeOutput.MemPos_ExeSection(const aname:string);
+ procedure TExeOutput.MemPos_ExeSection(exesec:TExeSection);
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;
+ exesec.MemPos:=CurrMemPos;
{ set position of object ObjSections }
- for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
+ for i:=0 to exesec.ObjSectionList.Count-1 do
begin
- objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
+ objsec:=TObjSection(exesec.ObjSectionList[i]);
CurrMemPos:=objsec.setmempos(CurrMemPos);
end;
{ calculate size of the section }
- CurrExeSec.Size:=CurrMemPos-CurrExeSec.MemPos;
+ exesec.Size:=CurrMemPos-exesec.MemPos;
+ end;
+
+
+ procedure TExeOutput.MemPos_ExeSection(const aname:string);
+ begin
+ { Section can be removed }
+ FCurrExeSec:=FindExeSection(aname);
+ if not assigned(CurrExeSec) then
+ exit;
+
+ MemPos_ExeSection(CurrExeSec);
end;
@@ -1956,34 +1951,29 @@ implementation
end;
- procedure TExeOutput.DataPos_ExeSection(const aname:string);
+ procedure TExeOutput.DataPos_ExeSection(exesec:TExeSection);
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
+ not(oso_debug in exesec.SecOptions) then
exit;
- if (oso_Data in currexesec.SecOptions) then
+ if (oso_Data in exesec.SecOptions) then
begin
CurrDataPos:=align(CurrDataPos,SectionDataAlign);
- CurrExeSec.DataPos:=CurrDataPos;
+ exesec.DataPos:=CurrDataPos;
end;
{ set position of object ObjSections }
- for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
+ for i:=0 to exesec.ObjSectionList.Count-1 do
begin
- objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
+ objsec:=TObjSection(exesec.ObjSectionList[i]);
if (oso_Data in objsec.SecOptions) then
begin
- if not(oso_Data in currexesec.SecOptions) then
+ if not(oso_Data in exesec.SecOptions) then
internalerror(200603043);
if not assigned(objsec.Data) then
internalerror(200603044);
@@ -1993,6 +1983,16 @@ implementation
end;
+ procedure TExeOutput.DataPos_ExeSection(const aname:string);
+ begin
+ { Section can be removed }
+ FCurrExeSec:=FindExeSection(aname);
+ if not assigned(CurrExeSec) then
+ exit;
+ DataPos_ExeSection(CurrExeSec);
+ end;
+
+
procedure TExeOutput.DataPos_EndExeSection;
begin
if not assigned(CurrExeSec) then
@@ -2002,18 +2002,7 @@ implementation
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;
@@ -2177,7 +2166,11 @@ implementation
exesym.ObjSymbol:=objsym;
exesym.State:=symstate_common;
end;
- CommonObjSymbols.add(objsym);
+ if assigned(objsym.objsection) and
+ (objsym.objsection.objdata=internalObjData) then
+ FProvidedObjSymbols.add(objsym)
+ else
+ CommonObjSymbols.add(objsym);
end;
end;
end;
@@ -2188,10 +2181,11 @@ implementation
VTInheritList:=TFPObjectList.Create(false);
{
- The symbol resolving is done in 3 steps:
+ The symbol resolving is done in 4 steps:
1. Register symbols from objects
2. Find symbols in static libraries
- 3. Define stil undefined common symbols
+ 3. Define symbols PROVIDEd by the link script
+ 4. Define still undefined common symbols
}
{ Step 1, Register symbols from objects }
@@ -2246,7 +2240,19 @@ implementation
end;
PackUnresolvedExeSymbols('after static libraries');
- { Step 3, Match common symbols or add to the globals }
+ { Step 3, handle symbols provided in script }
+ for i:=0 to FProvidedObjSymbols.count-1 do
+ begin
+ objsym:=TObjSymbol(FProvidedObjSymbols[i]);
+ if objsym.exesymbol.State=symstate_defined then
+ continue;
+ objsym.exesymbol.objsymbol:=objsym;
+ objsym.bind:=AB_GLOBAL;
+ objsym.exesymbol.State:=symstate_defined;
+ end;
+ PackUnresolvedExeSymbols('after defining symbols provided by link script');
+
+ { Step 4, Match common symbols or add to the globals }
firstcommon:=true;
for i:=0 to CommonObjSymbols.count-1 do
begin
@@ -2268,7 +2274,7 @@ implementation
end;
internalObjData.setsection(commonObjSection);
internalObjData.allocalign(var_align(objsym.size));
- commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_FUNCTION);
+ commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_DATA);
commonsym.size:=objsym.size;
internalObjData.alloc(objsym.size);
if assigned(exemap) then
@@ -2331,7 +2337,7 @@ implementation
exesec:=CExeSection.create(ExeSectionList,debuglinkname);
exesec.SecOptions:=[oso_data,oso_keep];
exesec.SecAlign:=4;
- objsec:=internalObjData.createsection(exesec.name,0,exesec.SecOptions);
+ objsec:=internalObjData.createsection(exesec.name,1,exesec.SecOptions);
internalObjData.writebytes(debuglink,len);
exesec.AddObjSection(objsec);
end;
@@ -2342,16 +2348,34 @@ implementation
end;
+ function ByAddress(item1,item2:pointer):longint;
+ var
+ sym1:TObjSymbol absolute item1;
+ sym2:TObjSymbol absolute item2;
+ begin
+ result:=sym1.address-sym2.address;
+ end;
+
+
procedure TExeOutput.PrintMemoryMap;
var
exesec : TExeSection;
objsec : TObjSection;
objsym : TObjSymbol;
- i,j,k : longint;
+ i,j,k,m: longint;
+ list : TFPList;
+ flag : boolean;
begin
if not assigned(exemap) then
exit;
+ { create a list of symbols sorted by address }
+ list:=TFPList.Create;
+ for i:=0 to ExeSymbolList.Count-1 do
+ list.Add(TExeSymbol(ExeSymbolList[i]).ObjSymbol);
+ list.Sort(@ByAddress);
+
exemap.AddMemoryMapHeader(ImageBase);
+ k:=0;
for i:=0 to ExeSectionList.Count-1 do
begin
exesec:=TExeSection(ExeSectionList[i]);
@@ -2360,13 +2384,43 @@ implementation
begin
objsec:=TObjSection(exesec.ObjSectionList[j]);
exemap.AddMemoryMapObjectSection(objsec);
- for k:=0 to objsec.ObjSymbolDefines.Count-1 do
+
+ while (k<list.Count) and (TObjSymbol(list[k]).Address<objsec.MemPos) do
+ inc(k);
+ while (k<list.Count) do
begin
- objsym:=TObjSymbol(objsec.ObjSymbolDefines[k]);
- exemap.AddMemoryMapSymbol(objsym);
+ objsym:=TObjSymbol(list[k]);
+ if objsym.address>objsec.MemPos+objsec.Size then
+ break;
+ if objsym.objsection=objsec then
+ exemap.AddMemoryMapSymbol(objsym)
+ else
+ begin
+ { Got a symbol with address falling into current section, but
+ belonging to a different section. This may happen for zero-length
+ sections because symbol list is sorted by address but not by section.
+ Do some look-ahead in this case. }
+ m:=k+1;
+ flag:=false;
+ while (m<list.Count) and (TObjSymbol(list[m]).Address=objsym.address) do
+ begin
+ if TObjSymbol(list[m]).objsection=objsec then
+ begin
+ flag:=true;
+ list.Exchange(k,m);
+ exemap.AddMemoryMapSymbol(TObjSymbol(list[k]));
+ break;
+ end;
+ inc(m);
+ end;
+ if not flag then
+ break;
+ end;
+ inc(k);
end;
end;
end;
+ list.Free;
end;
@@ -2394,10 +2448,6 @@ implementation
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
@@ -2841,12 +2891,28 @@ implementation
objsec:=TObjSection(exesec.ObjSectionlist[j]);
if not objsec.Used then
internalerror(200603301);
- objsec.FixupRelocs;
+ objsec.FixupRelocs(Self);
end;
end;
end;
+ procedure TExeOutput.RemoveUnusedExeSymbols;
+ 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.SetCurrMemPos(const AValue: qword);
begin
if AValue>MaxMemPos then
diff --git a/mips/compiler/ogcoff.pas b/mips/compiler/ogcoff.pas
index 157aa0a91f..61fc394f22 100644
--- a/mips/compiler/ogcoff.pas
+++ b/mips/compiler/ogcoff.pas
@@ -107,18 +107,9 @@ interface
coffrelocs,
coffrelocpos : aword;
public
- secidx : 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;
+ procedure fixuprelocs(Exe:TExeOutput);override;
end;
TCoffObjData = class(TObjData)
@@ -132,7 +123,6 @@ interface
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)
@@ -172,8 +162,9 @@ interface
TCoffObjInput = class(tObjInput)
private
- FCoffsyms,
- FCoffStrs : tdynamicarray;
+ FCoffsyms : tdynamicarray;
+ FCoffStrs : PChar;
+ FCoffStrSize: longword;
{ Convert symidx -> TObjSymbol }
FSymTbl : ^TObjSymbolArray;
{ Convert secidx -> TObjSection }
@@ -199,21 +190,6 @@ interface
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
FCoffStrs : tdynamicarray;
@@ -254,11 +230,7 @@ interface
procedure MemPos_ExeSection(const aname:string);override;
end;
- TObjSymbolrec = record
- sym : TObjSymbol;
- orgsize : aword;
- end;
- TObjSymbolArray = array[0..high(word)] of TObjSymbolrec;
+ TObjSymbolArray = array[0..high(word)] of TObjSymbol;
TObjSectionArray = array[0..high(smallint)] of TObjSection;
TDJCoffAssembler = class(tinternalassembler)
@@ -796,16 +768,11 @@ const pemagic : array[0..3] of byte = (
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
+ if (flags and (PE_SCN_LNK_REMOVE or PE_SCN_MEM_DISCARDABLE)=0) then
include(aoptions,oso_load);
{ read/write }
if flags and PE_SCN_MEM_WRITE<>0 then
- include(aoptions,oso_write)
- else
- include(aoptions,oso_readonly);
+ include(aoptions,oso_write);
{ alignment }
alignflag:=flags and PE_SCN_ALIGN_MASK;
if alignflag=PE_SCN_ALIGN_64BYTES then
@@ -845,7 +812,7 @@ const pemagic : array[0..3] of byte = (
end;
- procedure TCoffObjSection.fixuprelocs;
+ procedure TCoffObjSection.fixuprelocs(Exe:TExeOutput);
var
i,zero,address_size : longint;
objreloc : TObjRelocation;
@@ -981,7 +948,7 @@ const pemagic : array[0..3] of byte = (
else
{$endif arm}
inc(address,relocval);
- inc(address,relocsec.objdata.imagebase);
+ inc(address,exe.imagebase);
end;
else
internalerror(200604014);
@@ -1010,26 +977,6 @@ const pemagic : array[0..3] of byte = (
{****************************************************************************
- 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
****************************************************************************}
@@ -1169,29 +1116,13 @@ const pemagic : array[0..3] of byte = (
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);
+ inherited createcoff(n,false,TCoffObjSection);
end;
@@ -1201,7 +1132,7 @@ const pemagic : array[0..3] of byte = (
constructor TPECoffObjData.create(const n:string);
begin
- inherited createcoff(n,true,TPECoffObjSection);
+ inherited createcoff(n,true,TCoffObjSection);
end;
@@ -1254,14 +1185,14 @@ const pemagic : array[0..3] of byte = (
with TCoffObjSection(p) do
begin
Inc(plongword(arg)^);
- secidx:=plongword(arg)^;
+ index:=plongword(arg)^;
secsymidx:=symidx;
{ Both GNU and Microsoft toolchains write section symbols using
storage class 3 (STATIC).
No reason to use COFF_SYM_SECTION, it is silently converted to 3 by
PE binutils and causes warnings with DJGPP binutils. }
- write_symbol(name,mempos,secidx,COFF_SYM_LOCAL,1);
+ write_symbol(name,mempos,index,COFF_SYM_LOCAL,1);
{ AUX }
fillchar(secrec,sizeof(secrec),0);
secrec.len:=Size;
@@ -1389,13 +1320,13 @@ const pemagic : array[0..3] of byte = (
AB_GLOBAL :
begin
globalval:=COFF_SYM_GLOBAL;
- sectionval:=TCoffObjSection(objsym.objsection).secidx;
+ sectionval:=objsym.objsection.index;
value:=objsym.address;
end;
AB_LOCAL :
begin
globalval:=COFF_SYM_LOCAL;
- sectionval:=TCoffObjSection(objsym.objsection).secidx;
+ sectionval:=objsym.objsection.index;
value:=objsym.address;
end;
else
@@ -1465,11 +1396,9 @@ const pemagic : array[0..3] of byte = (
function TCoffObjOutput.writedata(data:TObjData):boolean;
var
- orgdatapos,
datapos,
sympos : aword;
i : longint;
- gotreloc : boolean;
header : tcoffheader;
begin
result:=false;
@@ -1485,9 +1414,7 @@ const pemagic : array[0..3] of byte = (
{ Sections first }
layoutsections(datapos);
{ relocs }
- orgdatapos:=datapos;
ObjSectionList.ForEachCall(@section_set_reloc_datapos,@datapos);
- gotreloc:=(orgdatapos<>datapos);
{ Symbols }
sympos:=datapos;
@@ -1499,22 +1426,15 @@ const pemagic : array[0..3] of byte = (
header.syms:=symidx;
if win32 then
begin
-{$ifdef arm}
+{$ifndef x86_64}
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;
+{$else x86_64}
+ header.flag:=PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
+{$endif x86_64}
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;
+ header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
FWriter.write(header,sizeof(header));
{ Section headers }
ObjSectionList.ForEachCall(@section_write_header,nil);
@@ -1567,7 +1487,8 @@ const pemagic : array[0..3] of byte = (
destructor TCoffObjInput.destroy;
begin
FCoffSyms.free;
- FCoffStrs.free;
+ if assigned(FCoffStrs) then
+ freemem(FCoffStrs);
if assigned(FSymTbl) then
freemem(FSymTbl);
if assigned(FSecTbl) then
@@ -1590,12 +1511,9 @@ const pemagic : array[0..3] of byte = (
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
+ if (FCoffStrs=nil) or (strpos>=FCoffStrSize) or (FCoffStrs[strpos]=#0) then
Internalerror(200205172);
+ result:=string(PChar(@FCoffStrs[strpos]));
end;
@@ -1664,9 +1582,9 @@ const pemagic : array[0..3] of byte = (
end;
end;
- p:=FSymTbl^[rel.sym].sym;
+ p:=FSymTbl^[rel.sym];
if assigned(p) then
- s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type)
+ s.addsymsizereloc(rel.address-s.mempos,p,p.size,rel_type)
else
begin
InputError('Failed reading coff file, can''t resolve symbol of relocation');
@@ -1694,7 +1612,7 @@ const pemagic : array[0..3] of byte = (
begin
nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
{ Allocate memory for symidx -> TObjSymbol table }
- FSymTbl:=AllocMem(nsyms*sizeof(TObjSymbolrec));
+ FSymTbl:=AllocMem(nsyms*sizeof(TObjSymbol));
{ Load the Symbols }
FCoffSyms.Seek(0);
symidx:=0;
@@ -1742,9 +1660,6 @@ const pemagic : array[0..3] of byte = (
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 :
@@ -1786,8 +1701,7 @@ const pemagic : array[0..3] of byte = (
else
internalerror(200602232);
end;
- FSymTbl^[symidx].sym:=objsym;
- FSymTbl^[symidx].orgsize:=size;
+ FSymTbl^[symidx]:=objsym;
{ read aux records }
for i:=1 to sym.aux do
begin
@@ -1822,7 +1736,6 @@ const pemagic : array[0..3] of byte = (
function TCoffObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
var
secalign : shortint;
- strsize,
strpos,
i : longint;
code : longint;
@@ -1837,7 +1750,6 @@ const pemagic : array[0..3] of byte = (
InputFileName:=AReader.FileName;
result:=false;
FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
- FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
with TCoffObjData(objdata) do
begin
{ Read COFF header }
@@ -1862,15 +1774,23 @@ const pemagic : array[0..3] of byte = (
exit;
end;
{ Strings }
- if not AReader.Read(strsize,4) then
+ if not AReader.Read(FCoffStrSize,4) then
begin
InputError('Error reading COFF string table');
exit;
end;
- if (strsize>4) and not AReader.ReadArray(FCoffStrs,Strsize-4) then
+ if (FCoffStrSize>4) then
begin
- InputError('Error reading COFF string table');
- exit;
+ { allocate an extra byte and null-terminate }
+ GetMem(FCoffStrs,FCoffStrSize+1);
+ FCoffStrs[FCoffStrSize]:=#0;
+ for i:=0 to 3 do
+ FCoffStrs[i]:=#0;
+ if not AReader.Read(FCoffStrs[4],FCoffStrSize-4) then
+ begin
+ InputError('Error reading COFF string table');
+ exit;
+ end;
end;
{ Section headers }
{ Allocate SecIdx -> TObjSection table, secidx is 1-based }
@@ -1907,14 +1827,14 @@ const pemagic : array[0..3] of byte = (
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
+ if (Pos('.edata',secname)=1) or
+ (Pos('.rsrc',secname)=1) or
{$ifndef x86_64}
- (Copy(secname,1,6)='.pdata') or
+ (Pos('.pdata',secname)=1) or
{$endif}
- (Copy(secname,1,4)='.fpc') then
+ (Pos('.fpc',secname)=1) then
include(secoptions,oso_keep);
- if (Copy(secname,1,6)='.idata') then
+ if (Pos('.idata',secname)=1) then
begin
{ TODO: idata keep can maybe replaced with grouping of text and idata}
include(secoptions,oso_keep);
@@ -1938,7 +1858,8 @@ const pemagic : array[0..3] of byte = (
{ Relocs }
ObjSectionList.ForEachCall(@objsections_read_relocs,nil);
end;
- FCoffStrs.Free;
+ if assigned(FCoffStrs) then
+ freemem(FCoffStrs);
FCoffStrs:=nil;
FCoffSyms.Free;
FCoffSyms:=nil;
@@ -1961,30 +1882,6 @@ const pemagic : array[0..3] of byte = (
{****************************************************************************
- 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
****************************************************************************}
@@ -2433,7 +2330,7 @@ const pemagic : array[0..3] of byte = (
begin
idataExeSec:=FindExeSection('.idata');
if idataExeSec<>nil then
- idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write] + [oso_readonly];
+ idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write];
end;
{ Section headers }
@@ -2483,7 +2380,7 @@ const pemagic : array[0..3] of byte = (
begin
inherited createcoff(false);
datapos_offset:=sizeof(go32v2stub);
- CExeSection:=TDJCoffExeSection;
+ CExeSection:=TExeSection;
CObjData:=TDJCoffObjData;
end;
@@ -2497,7 +2394,7 @@ const pemagic : array[0..3] of byte = (
constructor TPECoffexeoutput.create;
begin
inherited createcoff(true);
- CExeSection:=TPECoffExeSection;
+ CExeSection:=TExeSection;
CObjData:=TPECoffObjData;
end;
diff --git a/mips/compiler/ogelf.pas b/mips/compiler/ogelf.pas
index f270f24466..6af27003de 100644
--- a/mips/compiler/ogelf.pas
+++ b/mips/compiler/ogelf.pas
@@ -39,7 +39,6 @@ interface
type
TElfObjSection = class(TObjSection)
public
- secshidx : longint; { index for the section in symtab }
shstridx,
shtype,
shflags,
@@ -47,7 +46,19 @@ interface
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);
+ constructor create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint);
+ end;
+
+ TElfSymtabKind = (esk_obj,esk_exe,esk_dyn);
+
+ TElfSymtab = class(TElfObjSection)
+ public
+ kind: TElfSymtabKind;
+ fstrsec: TObjSection;
+ symidx: longint;
+ constructor create(aObjData:TObjData;aKind:TElfSymtabKind);reintroduce;
+ procedure writeSymbol(objsym:TObjSymbol);
+ procedure writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word);
end;
TElfObjData = class(TObjData)
@@ -60,21 +71,12 @@ interface
TElfObjectOutput = class(tObjOutput)
private
- symtabsect,
- strtabsect,
+ symtabsect: TElfSymtab;
shstrtabsect: TElfObjSection;
- {gotpcsect,
- gotoffsect,
- goTSect,
- plTSect,
- symsect : TElfObjSection;}
- symidx,
- localsyms : longint;
procedure createrelocsection(s:TElfObjSection;data:TObjData);
procedure createshstrtab(data:TObjData);
procedure createsymtab(data: TObjData);
procedure writesectionheader(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);
@@ -123,56 +125,48 @@ implementation
{$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;
+ R_X86_64_64 = 1; { Direct 64 bit }
+ R_X86_64_PC32 = 2; { PC relative 32 bit signed }
+ R_X86_64_GOT32 = 3; { 32 bit GOT entry }
+ R_X86_64_PLT32 = 4; { 32 bit PLT address }
+ R_X86_64_COPY = 5; { Copy symbol at runtime }
+ R_X86_64_GLOB_DAT = 6; { Create GOT entry }
+ R_X86_64_JUMP_SLOT = 7; { Create PLT entry }
+ R_X86_64_RELATIVE = 8; { Adjust by program base }
+ R_X86_64_GOTPCREL = 9; { 32 bit signed PC relative offset to GOT }
+ R_X86_64_32 = 10; { Direct 32 bit zero extended }
+ R_X86_64_32S = 11; { Direct 32 bit sign extended }
+ R_X86_64_16 = 12; { Direct 16 bit zero extended }
+ R_X86_64_PC16 = 13; { 16 bit sign extended PC relative }
+ R_X86_64_8 = 14; { Direct 8 bit sign extended }
+ R_X86_64_PC8 = 15; { 8 bit sign extended PC relative }
+ R_X86_64_DTPMOD64 = 16; { ID of module containing symbol }
+ R_X86_64_DTPOFF64 = 17; { Offset in module's TLS block }
+ R_X86_64_TPOFF64 = 18; { Offset in initial TLS block }
{ 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;
+ R_X86_64_DTPOFF32 = 21; { Offset in TLS block }
{ 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;
+ R_X86_64_TPOFF32 = 23; { Offset in initial TLS block }
+ R_X86_64_PC64 = 24; { PC relative 64-bit signed }
+ R_X86_64_GOTOFF64 = 25; { 64-bit offset from GOT base }
+ R_X86_64_GOTPC32 = 26; { PC-relative offset GOT }
+ R_X86_64_GOT64 = 27; { 64-bit GOT entry offset }
+ R_X86_64_GOTPCREL64 = 28; { 64-bit PC relative offset to GOT entry }
+ R_X86_64_GOTPC64 = 29; { 64-bit PC relative offset to GOT }
+ R_X86_64_GOTPLT64 = 30; { Like GOT64, indicates that PLT entry needed }
+ R_X86_64_PLTOFF64 = 31; { 64-bit GOT relative offset to PLT entry }
+ R_X86_64_SIZE32 = 32;
+ R_X86_64_SIZE64 = 33;
+ R_X86_64_GOTPC32_TLSDESC = 34;
+ R_X86_64_TLSDESC_CALL = 35;
+ R_X86_64_TLSDESC = 36;
+ R_X86_64_IRELATIVE = 37;
+ R_X86_64_GNU_VTINHERIT = 250; { GNU extension to record C++ vtable hierarchy }
+ R_X86_64_GNU_VTENTRY = 251; { GNU extension to record C++ vtable member usage }
{$endif x86_64}
{ ELFHeader.file_class }
@@ -245,6 +239,64 @@ implementation
STT_SECTION = 3;
STT_FILE = 4;
+ { program header types }
+ PT_NULL = 0;
+ PT_LOAD = 1;
+ PT_DYNAMIC = 2;
+ PT_INTERP = 3;
+ PT_NOTE = 4;
+ PT_SHLIB = 5;
+ PT_PHDR = 6;
+ PT_LOPROC = $70000000;
+ PT_HIPROC = $7FFFFFFF;
+
+ { program header flags }
+ PF_X = 1;
+ PF_W = 2;
+ PF_R = 4;
+ PF_MASKPROC = $F0000000;
+
+ { .dynamic tags }
+ DT_NULL = 0;
+ DT_NEEDED = 1;
+ DT_PLTRELSZ = 2;
+ DT_PLTGOT = 3;
+ DT_HASH = 4;
+ DT_STRTAB = 5;
+ DT_SYMTAB = 6;
+ DT_RELA = 7;
+ DT_RELASZ = 8;
+ DT_RELAENT = 9;
+ DT_STRSZ = 10;
+ DT_SYMENT = 11;
+ DT_INIT = 12;
+ DT_FINI = 13;
+ DT_SONAME = 14;
+ DT_RPATH = 15;
+ DT_SYMBOLIC = 16;
+ DT_REL = 17;
+ DT_RELSZ = 18;
+ DT_RELENT = 19;
+ DT_PLTREL = 20;
+ DT_DEBUG = 21;
+ DT_TEXTREL = 22;
+ DT_JMPREL = 23;
+ DT_BIND_NOW = 24;
+ DT_INIT_ARRAY = 25;
+ DT_FINI_ARRAY = 26;
+ DT_INIT_ARRAYSZ = 27;
+ DT_FINI_ARRAYSZ = 28;
+ DT_RUNPATH = 29;
+ DT_FLAGS = 30;
+ DT_ENCODING = 32;
+ DT_PREINIT_ARRAY = 32;
+ DT_PREINIT_ARRAYSZ = 33;
+ DT_NUM = 34;
+ DT_LOOS = $6000000D;
+ DT_HIOS = $6ffff000;
+ DT_LOPROC = $70000000;
+ DT_HIPROC = $7fffffff;
+
type
{ Structures which are written directly to the output file }
TElf32header=packed record
@@ -255,11 +307,11 @@ implementation
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_version : longword;
+ e_entry : longword; { entrypoint }
+ e_phoff : longword; { program header offset }
+ e_shoff : longword; { sections header offset }
+ e_flags : longword;
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 }
@@ -268,16 +320,16 @@ implementation
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;
+ sh_name : longword;
+ sh_type : longword;
+ sh_flags : longword;
+ sh_addr : longword;
+ sh_offset : longword;
+ sh_size : longword;
+ sh_link : longword;
+ sh_info : longword;
+ sh_addralign : longword;
+ sh_entsize : longword;
end;
TElf32proghdr=packed record
p_type : longword;
@@ -290,13 +342,14 @@ implementation
p_align : longword;
end;
TElf32reloc=packed record
- address : longint;
- info : longint; { bit 0-7: type, 8-31: symbol }
+ address : longword;
+ info : longword; { bit 0-7: type, 8-31: symbol }
+ addend : longint;
end;
TElf32symbol=packed record
- st_name : longint;
- st_value : longint;
- st_size : longint;
+ st_name : longword;
+ st_value : longword;
+ st_size : longword;
st_info : byte; { bit 0-3: type, 4-7: bind }
st_other : byte;
st_shndx : word;
@@ -317,11 +370,11 @@ implementation
padding : array[$07..$0f] of byte;
e_type : word;
e_machine : word;
- e_version : longint;
+ e_version : longword;
e_entry : qword; { entrypoint }
e_phoff : qword; { program header offset }
e_shoff : qword; { sections header offset }
- e_flags : longint;
+ e_flags : longword;
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 }
@@ -330,14 +383,14 @@ implementation
e_shstrndx : word; { index of string section header }
end;
telf64sechdr=packed record
- sh_name : longint;
- sh_type : longint;
+ sh_name : longword;
+ sh_type : longword;
sh_flags : qword;
sh_addr : qword;
sh_offset : qword;
sh_size : qword;
- sh_link : longint;
- sh_info : longint;
+ sh_link : longword;
+ sh_info : longword;
sh_addralign : qword;
sh_entsize : qword;
end;
@@ -357,7 +410,7 @@ implementation
addend : int64; { signed! }
end;
telf64symbol=packed record
- st_name : longint;
+ st_name : longword;
st_info : byte; { bit 0-3: type, 4-7: bind }
st_other : byte;
st_shndx : word;
@@ -394,6 +447,13 @@ implementation
telfdyn = telf32dyn;
{$endif cpu64bitaddr}
+{$ifdef x86_64}
+ const
+ relocs_use_addend:Boolean=True;
+{$else x86_64}
+ const
+ relocs_use_addend:Boolean=False;
+{$endif x86_64}
procedure MayBeSwapHeader(var h : telf32header);
begin
@@ -544,6 +604,7 @@ implementation
begin
address:=swapendian(address);
info:=swapendian(info);
+ addend:=swapendian(addend);
end;
end;
@@ -615,13 +676,9 @@ implementation
include(aoptions,oso_strings);
{ Section Flags }
if Ashflags and SHF_ALLOC<>0 then
- include(aoptions,oso_load)
- else
- include(aoptions,oso_noload);
+ include(aoptions,oso_load);
if Ashflags and SHF_WRITE<>0 then
- include(aoptions,oso_write)
- else
- include(aoptions,oso_readonly);
+ include(aoptions,oso_write);
if Ashflags and SHF_EXECINSTR<>0 then
include(aoptions,oso_executable);
end;
@@ -634,7 +691,7 @@ implementation
constructor TElfObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
begin
inherited create(AList,Aname,Aalign,aoptions);
- secshidx:=0;
+ index:=0;
shstridx:=0;
encodesechdrflags(aoptions,shtype,shflags);
shlink:=0;
@@ -644,13 +701,14 @@ implementation
end;
- constructor TElfObjSection.create_ext(AList:TFPHashObjectList;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint);
+ constructor TElfObjSection.create_ext(aobjdata:TObjData;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;
+ inherited create(aobjdata.ObjSectionList,Aname,Aalign,aoptions);
+ objdata:=aobjdata;
+ index:=0;
shstridx:=0;
shtype:=AshType;
shflags:=AshFlags;
@@ -671,7 +729,7 @@ implementation
{ we need at least the following sections }
createsection(sec_code);
{ always a non-PIC data section (will remain empty if doing PIC) }
- createsection('.data',sizeof(pint),sectiontype2options(sec_data));
+ createsection('.data',sectiontype2align(sec_data),sectiontype2options(sec_data));
createsection(sec_bss);
if (cs_create_pic in current_settings.moduleswitches) and
not(target_info.system in systems_darwin) then
@@ -848,24 +906,18 @@ implementation
procedure TElfObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);
var
symaddr : aint;
+ objreloc: TObjRelocation;
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;
+ objreloc:=nil;
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
+ (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 }
@@ -874,24 +926,140 @@ implementation
inc(data,symaddr-len-CurrObjSec.Size)
else
begin
- CurrObjSec.addsectionreloc(CurrObjSec.Size,p.objsection,reltype);
+ objreloc:=TObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,reltype);
+ CurrObjSec.ObjRelocations.Add(objreloc);
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}
+ objreloc:=TObjRelocation.CreateSymbol(CurrObjSec.Size,p,reltype);
+ CurrObjSec.ObjRelocations.Add(objreloc);
+ { If target is a local label and it isn't handled above,
+ patch its type in order to get it written to symtable.
+ This may happen e.g. when taking address of Pascal label in PIC mode. }
+ if (p.bind=AB_LOCAL) and (p.typ=AT_LABEL) then
+ p.typ:=AT_ADDR;
end;
end;
+ if assigned(objreloc) then
+ begin
+ objreloc.size:=len;
+ if reltype in [RELOC_RELATIVE,RELOC_PLT32{$ifdef x86_64},RELOC_GOTPCREL{$endif}] then
+ dec(data,len);
+ if relocs_use_addend then
+ begin
+ objreloc.orgsize:=data;
+ data:=0;
+ end;
+ end;
CurrObjSec.write(data,len);
end;
{****************************************************************************
+ TElfSymtab
+****************************************************************************}
+
+ const
+ symsecnames: array[boolean] of string[8] = ('.symtab','.dynsym');
+ strsecnames: array[boolean] of string[8] = ('.strtab','.dynstr');
+ symsectypes: array[boolean] of longint = (SHT_SYMTAB,SHT_DYNSYM);
+ symsecattrs: array[boolean] of longint = (0,SHF_ALLOC);
+
+
+ constructor TElfSymtab.create(aObjData:TObjData;aKind:TElfSymtabKind);
+ var
+ dyn:boolean;
+ begin
+ dyn:=(aKind=esk_dyn);
+ create_ext(aObjData,symsecnames[dyn],symsectypes[dyn],symsecattrs[dyn],0,0,sizeof(pint),sizeof(TElfSymbol));
+ fstrsec:=TElfObjSection.create_ext(aObjData,strsecnames[dyn],SHT_STRTAB,symsecattrs[dyn],0,0,1,0);
+ fstrsec.writestr(#0);
+ writezeros(sizeof(TElfSymbol));
+ symidx:=1;
+ shinfo:=1;
+ kind:=aKind;
+ end;
+
+ procedure TElfSymtab.writeInternalSymbol(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(shinfo);
+ MaybeSwapElfSymbol(elfsym);
+ write(elfsym,sizeof(elfsym));
+ end;
+
+ procedure TElfSymtab.writeSymbol(objsym:TObjSymbol);
+ var
+ elfsym:TElfSymbol;
+ begin
+ fillchar(elfsym,sizeof(elfsym),0);
+ { symbolname, write the #0 separate to overcome 255+1 char not possible }
+ elfsym.st_name:=fstrsec.writestr(objsym.name);
+ fstrsec.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(shinfo);
+ end;
+ AB_COMMON :
+ begin
+ elfsym.st_value:=$10; { ?? should not be hardcoded }
+ elfsym.st_info:=STB_GLOBAL shl 4;
+ elfsym.st_shndx:=SHN_COMMON;
+ 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
+ begin
+ if kind<>esk_obj then
+ begin
+ { TODO }
+ end
+ else
+ begin
+ if assigned(objsym.objsection) then
+ elfsym.st_shndx:=objsym.objsection.index
+ else
+ elfsym.st_shndx:=SHN_UNDEF;
+ objsym.symidx:=symidx;
+ end;
+ end;
+ inc(symidx);
+ MaybeSwapElfSymbol(elfsym);
+ write(elfsym,sizeof(TElfSymbol));
+ end;
+
+{****************************************************************************
TElfObjectOutput
****************************************************************************}
@@ -909,35 +1077,22 @@ implementation
objreloc : TObjRelocation;
relsym,
reltyp : longint;
- relocsect : TObjSection;
-{$ifdef x86_64}
- tmp: aint;
- asize: longint;
-{$endif x86_64}
+ relocsect : TElfObjSection;
begin
with data 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}
+ if relocs_use_addend then
+ relocsect:=TElfObjSection.create_ext(data,'.rela'+s.name,SHT_RELA,0,symtabsect.index,s.index,4,3*sizeof(pint))
+ else
+ relocsect:=TElfObjSection.create_ext(data,'.rel'+s.name,SHT_REL,0,symtabsect.index,s.index,4,2*sizeof(pint));
{ 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;
+ rel.addend:=objreloc.orgsize;
{ when things settle down, we can create processor specific
derived classes }
@@ -952,67 +1107,40 @@ implementation
RELOC_GOTPC :
reltyp:=R_386_GOTPC;
RELOC_PLT32 :
- begin
- reltyp:=R_386_PLT32;
- end;
+ reltyp:=R_386_PLT32;
{$endif i386}
{$ifdef sparc}
RELOC_ABSOLUTE :
reltyp:=R_SPARC_32;
{$endif sparc}
{$ifdef x86_64}
+ { Note: 8 and 16-bit relocations are known to be non-conformant with
+ AMD64 ABI, so they aren't handled. }
RELOC_RELATIVE :
- begin
- reltyp:=R_X86_64_PC32;
- { length of the relocated location is handled here }
- rel.addend:=-4;
- end;
+ if objreloc.size=8 then
+ reltyp:=R_X86_64_PC64
+ else if objreloc.size=4 then
+ reltyp:=R_X86_64_PC32
+ else
+ InternalError(2012061900);
RELOC_ABSOLUTE :
- reltyp:=R_X86_64_64;
+ if objreloc.size=8 then
+ reltyp:=R_X86_64_64
+ else if objreloc.size=4 then
+ reltyp:=R_X86_64_32
+ else
+ InternalError(2012061901);
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;
+ reltyp:=R_X86_64_GOTPCREL;
RELOC_PLT32 :
- begin
- reltyp:=R_X86_64_PLT32;
- { length of the relocated location is handled here }
- rel.addend:=-4;
- end;
+ reltyp:=R_X86_64_PLT32;
{$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
@@ -1036,107 +1164,34 @@ implementation
rel.info:=(relsym shl 8) or reltyp;
{$endif cpu64bitaddr}
{ write reloc }
+ { ElfXX_Rel is essentially ElfXX_Rela without the addend field. }
MaybeSwapElfReloc(rel);
- relocsect.write(rel,sizeof(rel));
+ relocsect.write(rel,relocsect.shentsize);
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);
- MaybeSwapElfSymbol(elfsym);
- symtabsect.write(elfsym,sizeof(elfsym));
- end;
-
-
procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
begin
- TObjSection(p).secsymidx:=symidx;
- write_internal_symbol(0,STT_SECTION,TElfObjSection(p).secshidx);
+ { Must not write symbols for internal sections like .symtab }
+ { TODO: maybe use inclusive list of section types instead }
+ if (TElfObjSection(p).shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
+ exit;
+ TObjSection(p).secsymidx:=symtabsect.symidx;
+ symtabsect.writeInternalSymbol(0,STT_SECTION,TObjSection(p).index);
end;
procedure TElfObjectOutput.createsymtab(data: TObjData);
-
- procedure WriteSym(objsym:TObjSymbol);
- var
- elfsym : telfsymbol;
- 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);
- MaybeSwapElfSymbol(elfsym);
- symtabsect.write(elfsym,sizeof(elfsym));
- end;
-
var
i : longint;
objsym : TObjSymbol;
begin
with data do
begin
- symidx:=0;
- localsyms:=0;
- { empty entry }
- write_internal_symbol(0,0,0);
{ filename entry }
- write_internal_symbol(1,STT_FILE,SHN_ABS);
+ symtabsect.writeInternalSymbol(1,STT_FILE,SHN_ABS);
{ section }
ObjSectionList.ForEachCall(@section_write_symbol,nil);
{ First the Local Symbols, this is required by ELF. The localsyms
@@ -1146,18 +1201,17 @@ implementation
begin
objsym:=TObjSymbol(ObjSymbolList[i]);
if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
- WriteSym(objsym);
+ symtabsect.WriteSymbol(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);
+ symtabsect.WriteSymbol(objsym);
end;
{ update the .symtab section header }
- symtabsect.shlink:=strtabsect.secshidx;
- symtabsect.shinfo:=localsyms;
+ symtabsect.shlink:=symtabsect.fstrsec.index;
end;
end;
@@ -1199,7 +1253,7 @@ implementation
procedure TElfObjectOutput.section_count_sections(p:TObject;arg:pointer);
begin
- TElfObjSection(p).secshidx:=pword(arg)^;
+ TElfObjSection(p).index:=pword(arg)^;
inc(pword(arg)^);
end;
@@ -1228,16 +1282,15 @@ implementation
with data 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);
+ symtabsect:=TElfSymtab.create(data,esk_obj);
+ shstrtabsect:=TElfObjSection.create_ext(data,'.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);
+ TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,0,0,1,0);
+ { insert filename as first in strtab }
+ symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource));
+ symtabsect.fstrsec.writestr(#0);
{ calc amount of sections we have }
nsections:=1;
{ also create the index in the section header table }
@@ -1276,12 +1329,12 @@ implementation
header.e_type:=ET_REL;
header.e_machine:=ELFMACHINE;
{$ifdef arm}
- if (current_settings.fputype=cpu_soft) then
+ if (current_settings.fputype=fpu_soft) then
header.e_flags:=$600;
{$endif arm}
header.e_version:=1;
header.e_shoff:=shoffset;
- header.e_shstrndx:=shstrtabsect.secshidx;
+ header.e_shstrndx:=shstrtabsect.index;
header.e_shnum:=nsections;
header.e_ehsize:=sizeof(telfheader);
diff --git a/mips/compiler/options.pas b/mips/compiler/options.pas
index 5392c76882..b277d8352b 100644
--- a/mips/compiler/options.pas
+++ b/mips/compiler/options.pas
@@ -2746,7 +2746,7 @@ begin
def_system_macro('FPC_STATICRIPFIXED');
def_system_macro('FPC_VARIANTCOPY_FIXED');
def_system_macro('FPC_DYNARRAYCOPY_FIXED');
-{$if defined(x86) or defined(powerpc) or defined(powerpc64)}
+{$if defined(x86) or defined(powerpc) or defined(powerpc64) or defined(cpuarm)}
def_system_macro('FPC_HAS_INTERNAL_ABS_LONG');
{$endif}
def_system_macro('FPC_HAS_UNICODESTRING');
@@ -2887,8 +2887,12 @@ begin
def_system_macro('CPUMIPSEL');
def_system_macro('CPUMIPSEL32');
def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
def_system_macro('FPC_CURRENCY_IS_INT64');
def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
{$endif mipsel}
{$ifdef mipseb}
@@ -2897,8 +2901,12 @@ begin
def_system_macro('CPUMIPSEB');
def_system_macro('CPUMIPSEB32');
def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
def_system_macro('FPC_CURRENCY_IS_INT64');
def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
{$endif}
{ read configuration file }
diff --git a/mips/compiler/paramgr.pas b/mips/compiler/paramgr.pas
index 1f6c59ac9c..04cd690fc0 100644
--- a/mips/compiler/paramgr.pas
+++ b/mips/compiler/paramgr.pas
@@ -81,7 +81,7 @@ unit paramgr;
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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def: tdef; var cgpara : tcgpara);virtual;abstract;
{# allocate an individual pcgparalocation that's part of a tcgpara
@@ -140,6 +140,10 @@ unit paramgr;
function use_fixed_stack: boolean;
{ whether stack pointer can be changed in the middle of procedure }
function use_stackalloc: boolean;
+ strict protected
+ { common part of get_funcretloc; returns true if retloc is completely
+ initialized afterwards }
+ function set_common_funcretloc_info(p : tabstractprocdef; def: tdef; out retcgsize: tcgsize; out retloc: tcgpara): boolean;
end;
@@ -492,6 +496,54 @@ implementation
result:=not use_fixed_stack;
end;
+
+ function tparamanager.set_common_funcretloc_info(p : tabstractprocdef; def: tdef; out retcgsize: tcgsize; out retloc: tcgpara): boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ result:=true;
+ retloc.init;
+ retloc.def:=def;
+ retloc.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=retloc.add_location;
+ retloc.size:=OS_NO;
+ retcgsize:=OS_NO;
+ retloc.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
+ if is_implicit_pointer_object_type(tdef(p.owner.defowner)) then
+ retloc.def:=tdef(p.owner.defowner)
+ else
+ retloc.def:=getpointerdef(tdef(p.owner.defowner));
+ retcgsize:=OS_ADDR;
+ retloc.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ retloc.intsize:=def.size;
+ end;
+ retloc.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ retloc.def:=getpointerdef(def);
+ paraloc:=retloc.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+ result:=false;
+ end;
+
initialization
;
finalization
diff --git a/mips/compiler/pdecobj.pas b/mips/compiler/pdecobj.pas
index 535f810c9a..f284fda740 100644
--- a/mips/compiler/pdecobj.pas
+++ b/mips/compiler/pdecobj.pas
@@ -133,16 +133,20 @@ implementation
consume(_SEMICOLON);
include(current_structdef.objectoptions,oo_has_constructor);
{ Set return type, class and record constructors return the
- created instance, object constructors return boolean }
+ created instance, helper types return the extended type,
+ object constructors return boolean }
if is_class(pd.struct) or
is_record(pd.struct) or
is_javaclass(pd.struct) then
pd.returndef:=pd.struct
else
+ if is_objectpascal_helper(pd.struct) then
+ pd.returndef:=tobjectdef(pd.struct).extendeddef
+ else
{$ifdef CPU64bitaddr}
- pd.returndef:=bool64type;
+ pd.returndef:=bool64type;
{$else CPU64bitaddr}
- pd.returndef:=bool32type;
+ pd.returndef:=bool32type;
{$endif CPU64bitaddr}
constr_destr_finish_head(pd,pd.struct);
result:=pd;
@@ -1405,6 +1409,10 @@ implementation
include(current_structdef.defoptions, df_generic);
parse_generic:=(df_generic in current_structdef.defoptions);
+ { in non-Delphi modes we need a strict private symbol without type
+ count and type parameters in the name to simply resolving }
+ maybe_insert_generic_rename_symbol(n,genericlist);
+
{ parse list of parent classes }
{ for record helpers in mode Delphi this is not allowed }
if not (is_objectpascal_helper(current_objectdef) and
diff --git a/mips/compiler/pdecsub.pas b/mips/compiler/pdecsub.pas
index cc541b16b6..73ad84b958 100644
--- a/mips/compiler/pdecsub.pas
+++ b/mips/compiler/pdecsub.pas
@@ -106,7 +106,7 @@ implementation
objcutil,
{ parser }
scanner,
- pbase,pexpr,ptype,pdecl,pparautl
+ pbase,pexpr,ptype,pdecl,pparautl,pgenutil
{$ifdef jvm}
,pjvm
{$endif}
@@ -387,7 +387,7 @@ implementation
if is_shortstring(hdef) then
begin
case varspez of
- vs_var,vs_out,vs_constref:
+ vs_var,vs_out:
begin
{ not 100% Delphi-compatible: type xstr=string[255] cannot
become an openstring there, while here it can }
@@ -680,8 +680,44 @@ implementation
Message1(type_e_generic_declaration_does_not_match,genname);
srsym:=nil;
exit;
+ end
+ end;
+ end;
+
+ procedure consume_generic_interface;
+ var
+ genparalist : tfpobjectlist;
+ prettyname,
+ specializename : ansistring;
+ genname,
+ ugenname : tidstring;
+ gencount : string;
+ begin
+ consume(_LSHARPBRACKET);
+ genparalist:=tfpobjectlist.create(false);
+
+ if not parse_generic_specialization_types(genparalist,prettyname,specializename,nil) then
+ srsym:=generrorsym
+ else
+ begin
+ str(genparalist.count,gencount);
+ genname:=sp+'$'+gencount;
+ if not parse_generic then
+ genname:=generate_generic_name(genname,specializename);
+ ugenname:=upper(genname);
+
+ srsym:=search_object_name(ugenname,false);
+
+ if not assigned(srsym) then
+ begin
+ Message1(type_e_generic_declaration_does_not_match,sp+'<'+prettyname+'>');
+ srsym:=nil;
+ exit;
end;
end;
+
+ genparalist.free;
+ consume(_RSHARPBRACKET);
end;
begin
@@ -700,16 +736,35 @@ implementation
(astruct.typ=objectdef) and
assigned(tobjectdef(astruct).ImplementedInterfaces) and
(tobjectdef(astruct).ImplementedInterfaces.count>0) and
- try_to_consume(_POINT) then
+ (
+ (token = _POINT) or
+ (token = _LSHARPBRACKET)
+ ) then
begin
- srsym:=search_object_name(sp,true);
+ if token = _POINT then
+ begin
+ consume(_POINT);
+ srsym:=search_object_name(sp,true);
+ end
+ else
+ begin
+ consume_generic_interface;
+ consume(_POINT);
+ { srsym is now either an interface def or generrordef }
+ end;
{ 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);
+ Message(parser_e_interface_id_expected)
+ else
+ { in case of a generic or specialized interface we need to use the
+ name of the def instead of the symbol, so that always the correct
+ name is used }
+ if [df_generic,df_specialization]*ttypesym(srsym).typedef.defoptions<>[] then
+ sp:=tobjectdef(ttypesym(srsym).typedef).objname^;
{ must be a directly implemented interface }
if Assigned(ImplIntf.ImplementsGetter) then
Message2(parser_e_implements_no_mapping,ImplIntf.IntfDef.typename,astruct.objrealname^);
@@ -1107,10 +1162,13 @@ implementation
is_javaclass(pd.struct) then
pd.returndef:=pd.struct
else
+ if is_objectpascal_helper(pd.struct) then
+ pd.returndef:=tobjectdef(pd.struct).extendeddef
+ else
{$ifdef CPU64bitaddr}
- pd.returndef:=bool64type;
+ pd.returndef:=bool64type;
{$else CPU64bitaddr}
- pd.returndef:=bool32type;
+ pd.returndef:=bool32type;
{$endif CPU64bitaddr}
end
else
diff --git a/mips/compiler/pexpr.pas b/mips/compiler/pexpr.pas
index 78fae9233d..520428b5ff 100644
--- a/mips/compiler/pexpr.pas
+++ b/mips/compiler/pexpr.pas
@@ -2199,10 +2199,7 @@ implementation
(
(token=_LKLAMMER) or
(
- (
- (m_tp7 in current_settings.modeswitches) or
- (m_delphi in current_settings.modeswitches)
- ) and
+ (([m_tp7,m_delphi,m_mac] * current_settings.modeswitches) <> []) and
(afterassignment or in_args)
)
) then
diff --git a/mips/compiler/pgenutil.pas b/mips/compiler/pgenutil.pas
index 02055054ea..215b7f1be7 100644
--- a/mips/compiler/pgenutil.pas
+++ b/mips/compiler/pgenutil.pas
@@ -29,12 +29,17 @@ interface
uses
{ common }
cclasses,
+ { global }
+ globtype,
{ symtable }
symtype,symdef,symbase;
procedure generate_specialization(var tt:tdef;parse_class_parent:boolean;_prettyname:string;parsedtype:tdef;symname:string);
function parse_generic_parameters:TFPObjectList;
+ function parse_generic_specialization_types(genericdeflist:tfpobjectlist;out prettyname,specializename:ansistring;parsedtype:tdef):boolean;
procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
+ procedure maybe_insert_generic_rename_symbol(const name:tidstring;genericlist:tfpobjectlist);
+ function generate_generic_name(const name:tidstring;specializename:ansistring):tidstring;
type
tspecializationstate = record
@@ -51,7 +56,7 @@ uses
{ common }
cutils,fpccrc,
{ global }
- globals,globtype,tokens,verbose,
+ globals,tokens,verbose,
{ symtable }
symconst,symsym,symtable,
{ modules }
@@ -187,59 +192,7 @@ uses
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.typename;
- 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.typename;
- 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;
-
+ err:=not parse_generic_specialization_types(genericdeflist,prettyname,specializename,parsedtype);
if err then
begin
try_to_consume(_RSHARPBRACKET);
@@ -257,7 +210,8 @@ uses
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
+ if assigned(genericdef) and
+ ([df_generic,df_specialization]*genericdef.defoptions<>[]) then
begin
{ remove the type count suffix from the generic's name }
for i:=Length(genname) downto 1 do
@@ -266,6 +220,15 @@ uses
genname:=copy(genname,1,i-1);
break;
end;
+ { in case of a specialization we've only reached the specialization
+ checksum yet }
+ if df_specialization in genericdef.defoptions then
+ 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);
@@ -292,8 +255,7 @@ uses
genericdef:=tstoreddef(ttypesym(srsym).typedef);
{ build the new type's name }
- crc:=UpdateCrc32(0,specializename[1],length(specializename));
- finalspecializename:=genname+'$crc'+hexstr(crc,8);
+ finalspecializename:=generate_generic_name(genname,specializename);
ufinalspecializename:=upper(finalspecializename);
prettyname:=genericdef.typesym.prettyname+'<'+prettyname+'>';
@@ -557,6 +519,67 @@ uses
until not try_to_consume(_COMMA) ;
end;
+ function parse_generic_specialization_types(genericdeflist:tfpobjectlist;out prettyname,specializename:ansistring;parsedtype:tdef):boolean;
+ var
+ old_block_type : tblock_type;
+ first : boolean;
+ typeparam : tnode;
+ begin
+ result:=true;
+ if genericdeflist=nil then
+ internalerror(2012061401);
+ { 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.typename;
+ 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;
+ typeparam:=factor(false,true);
+ if typeparam.nodetype=typen then
+ begin
+ if df_generic in typeparam.resultdef.defoptions then
+ Message(parser_e_no_generics_as_params);
+ genericdeflist.Add(typeparam.resultdef);
+ if not assigned(typeparam.resultdef.typesym) then
+ message(type_e_generics_cannot_reference_itself)
+ else
+ begin
+ specializename:=specializename+'$'+typeparam.resultdef.typename;
+ if first then
+ prettyname:=prettyname+typeparam.resultdef.typesym.prettyname
+ else
+ prettyname:=prettyname+','+typeparam.resultdef.typesym.prettyname;
+ end;
+ end
+ else
+ begin
+ Message(type_e_type_id_expected);
+ result:=false;
+ end;
+ typeparam.free;
+ first:=false;
+ end;
+ block_type:=old_block_type;
+ end;
procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
var
@@ -587,6 +610,51 @@ uses
end;
end;
+ procedure maybe_insert_generic_rename_symbol(const name:tidstring;genericlist:tfpobjectlist);
+ var
+ gensym : ttypesym;
+ begin
+ { for generics in non-Delphi modes we insert a private type symbol
+ that has the same base name as the currently parsed generic and
+ that references this defs }
+ if not (m_delphi in current_settings.modeswitches) and
+ (
+ (
+ parse_generic and
+ assigned(genericlist) and
+ (genericlist.count>0)
+ ) or
+ (
+ assigned(current_specializedef) and
+ assigned(current_structdef.genericdef) and
+ (current_structdef.genericdef.typ in [objectdef,recorddef]) and
+ (pos('$',name)>0)
+ )
+ ) then
+ begin
+ { we need to pass nil as def here, because the constructor wants
+ to set the typesym of the def which is not what we want }
+ gensym:=ttypesym.create(copy(name,1,pos('$',name)-1),nil);
+ gensym.typedef:=current_structdef;
+ include(gensym.symoptions,sp_internal);
+ { the symbol should be only visible to the generic class
+ itself }
+ gensym.visibility:=vis_strictprivate;
+ symtablestack.top.insert(gensym);
+ end;
+ end;
+
+ function generate_generic_name(const name:tidstring;specializename:ansistring):tidstring;
+ var
+ crc : cardinal;
+ begin
+ if specializename='' then
+ internalerror(2012061901);
+ { build the new type's name }
+ crc:=UpdateCrc32(0,specializename[1],length(specializename));
+ result:=name+'$crc'+hexstr(crc,8);
+ end;
+
procedure specialization_init(genericdef:tdef;var state: tspecializationstate);
var
pu : tused_unit;
@@ -617,10 +685,18 @@ uses
if sym.typ=unitsym then
unitsyms.add(upper(sym.realname),sym);
end;
- { add all interface units to the new symtable stack }
+ { add all units if we are specializing inside the current unit (as the
+ generic could have been declared in the implementation part), but load
+ only interface units, if we are in a different unit as then the generic
+ needs to be in the interface section }
pu:=tused_unit(hmodule.used_units.first);
while assigned(pu) do
begin
+ if (hmodule<>current_module) and not pu.in_interface then
+ begin
+ pu:=tused_unit(pu.next);
+ continue;
+ end;
if not assigned(pu.u.globalsymtable) then
internalerror(200705153);
symtablestack.push(pu.u.globalsymtable);
diff --git a/mips/compiler/powerpc/cpubase.pas b/mips/compiler/powerpc/cpubase.pas
index a33e214d48..629ccfee4a 100644
--- a/mips/compiler/powerpc/cpubase.pas
+++ b/mips/compiler/powerpc/cpubase.pas
@@ -352,7 +352,7 @@ uses
);
{ this is only for the generic code which is not used for this architecture }
- saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+ 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
diff --git a/mips/compiler/powerpc/cpupara.pas b/mips/compiler/powerpc/cpupara.pas
index 8c3266bc5e..0f4970889f 100644
--- a/mips/compiler/powerpc/cpupara.pas
+++ b/mips/compiler/powerpc/cpupara.pas
@@ -37,7 +37,7 @@ unit cpupara;
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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -78,14 +78,15 @@ unit cpupara;
end;
- procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
begin
cgpara.reset;
- cgpara.size:=OS_ADDR;
- cgpara.intsize:=sizeof(pint);
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(calloption);
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -256,38 +257,8 @@ unit cpupara;
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;
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
paraloc:=result.add_location;
{ Return in FPU register? }
@@ -403,12 +374,9 @@ unit cpupara;
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
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
- paradef:=voidpointertype;
+ paradef:=getpointerdef(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@@ -466,6 +434,7 @@ unit cpupara;
hp.paraloc[side].alignment:=std_param_align;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].def:=paradef;
if (target_info.abi = abi_powerpc_aix) and
(paradef.typ in [recorddef,arraydef]) then
hp.paraloc[side].composite:=true;
diff --git a/mips/compiler/powerpc/nppcmat.pas b/mips/compiler/powerpc/nppcmat.pas
index 4c49448727..faa2050082 100644
--- a/mips/compiler/powerpc/nppcmat.pas
+++ b/mips/compiler/powerpc/nppcmat.pas
@@ -403,7 +403,13 @@ end;
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
+ else }
+ if shiftval = 0 then
+ begin
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reghi,location.register64.reghi);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,location.register64.reglo);
+ end
+ else if shiftval > 31 then
begin
if nodetype = shln then
begin
diff --git a/mips/compiler/powerpc64/cpubase.pas b/mips/compiler/powerpc64/cpubase.pas
index 57cea3cbf4..ded99ac0e4 100644
--- a/mips/compiler/powerpc64/cpubase.pas
+++ b/mips/compiler/powerpc64/cpubase.pas
@@ -350,7 +350,7 @@ const
);
{ this is only for the generic code which is not used for this architecture }
- saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+ 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
diff --git a/mips/compiler/powerpc64/cpupara.pas b/mips/compiler/powerpc64/cpupara.pas
index 8a6164cd3a..b17a4b7ae3 100644
--- a/mips/compiler/powerpc64/cpupara.pas
+++ b/mips/compiler/powerpc64/cpupara.pas
@@ -40,8 +40,7 @@ type
function push_addr_param(varspez: tvarspez; def: tdef; calloption:
tproccalloption): boolean; override;
- procedure getintparaloc(calloption: tproccalloption; nr: longint; var
- cgpara: TCGPara); override;
+ procedure getintparaloc(calloption: tproccalloption; nr: longint; def: tdef; 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;
@@ -79,15 +78,15 @@ begin
result := [RS_F0..RS_F13];
end;
-procedure tppcparamanager.getintparaloc(calloption: tproccalloption; nr:
- longint; var cgpara: TCGPara);
+procedure tppcparamanager.getintparaloc(calloption: tproccalloption; nr: longint; def : tdef; var cgpara: tcgpara);
var
paraloc: pcgparalocation;
begin
cgpara.reset;
- cgpara.size := OS_ADDR;
- cgpara.intsize := sizeof(pint);
+ cgpara.size := def_cgsize(def);
+ cgpara.intsize := tcgsize2size[cgpara.size];
cgpara.alignment := get_para_align(calloption);
+ cgpara.def:=def;
paraloc := cgpara.add_location;
with paraloc^ do begin
size := OS_INT;
@@ -215,38 +214,8 @@ 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;
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
paraloc:=result.add_location;
{ Return in FPU register? }
@@ -334,11 +303,8 @@ begin
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;
+ if push_addr_param(hp.varspez, paradef, p.proccalloption) then begin
+ paradef := getpointerdef(paradef);
loc := LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@@ -390,6 +356,7 @@ begin
hp.paraloc[side].alignment := std_param_align;
hp.paraloc[side].size := paracgsize;
hp.paraloc[side].intsize := paralen;
+ hp.paraloc[side].def := paradef;
if (paralen = 0) then
if (paradef.typ = recorddef) then begin
paraloc := hp.paraloc[side].add_location;
diff --git a/mips/compiler/pparautl.pas b/mips/compiler/pparautl.pas
index 434044db04..66baa37254 100644
--- a/mips/compiler/pparautl.pas
+++ b/mips/compiler/pparautl.pas
@@ -51,6 +51,7 @@ implementation
begin
if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
not is_void(pd.returndef) and
+ not (df_generic in pd.defoptions) and
paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
begin
storepos:=current_tokenpos;
@@ -243,7 +244,11 @@ implementation
{ 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
+ { we also need to do this for a generic procdef as we didn't allow
+ the creation of a result symbol in insert_funcret_para, but we need
+ a valid funcretsym }
+ if (df_generic in pd.defoptions) or
+ 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);
diff --git a/mips/compiler/ppcgen/cgppc.pas b/mips/compiler/ppcgen/cgppc.pas
index 4e482f90bd..4facd00538 100644
--- a/mips/compiler/ppcgen/cgppc.pas
+++ b/mips/compiler/ppcgen/cgppc.pas
@@ -657,7 +657,7 @@ unit cgppc;
if (target_info.system in [system_powerpc_darwin]) then
begin
paraloc1.init;
- paramanager.getintparaloc(pocall_cdecl,1,paraloc1);
+ paramanager.getintparaloc(pocall_cdecl,1,voidpointertype,paraloc1);
a_load_reg_cgpara(list,OS_ADDR,NR_R0,paraloc1);
paramanager.freecgpara(list,paraloc1);
paraloc1.done;
diff --git a/mips/compiler/ppu.pas b/mips/compiler/ppu.pas
index 3ecad1736e..f9ee577b07 100644
--- a/mips/compiler/ppu.pas
+++ b/mips/compiler/ppu.pas
@@ -43,7 +43,7 @@ type
{$endif Test_Double_checksum}
const
- CurrentPPUVersion = 149;
+ CurrentPPUVersion = 151;
{ buffer sizes }
maxentrysize = 1024;
diff --git a/mips/compiler/pstatmnt.pas b/mips/compiler/pstatmnt.pas
index 69bd5ae084..089e5b955e 100644
--- a/mips/compiler/pstatmnt.pas
+++ b/mips/compiler/pstatmnt.pas
@@ -1382,6 +1382,7 @@ implementation
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 (df_generic in current_procinfo.procdef.defoptions) 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
@@ -1395,6 +1396,7 @@ implementation
register.
}
if assigned(current_procinfo.procdef.funcretsym) and
+ not (df_generic in current_procinfo.procdef.defoptions) and
(not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
diff --git a/mips/compiler/psub.pas b/mips/compiler/psub.pas
index 692ec26dfe..73439091e4 100644
--- a/mips/compiler/psub.pas
+++ b/mips/compiler/psub.pas
@@ -116,7 +116,7 @@ implementation
opttail,
optcse,optloop,
optutils
-{$if defined(arm) or defined(powerpc) or defined(powerpc64) or defined(avr)}
+{$if defined(arm) or defined(avr) or defined(fpc_compiler_has_fixup_jmps)}
,aasmcpu
{$endif arm}
{$ifndef NOOPT}
@@ -404,6 +404,7 @@ implementation
para : tcallparanode;
call : tcallnode;
newstatement : tstatementnode;
+ def : tabstractrecorddef;
begin
result:=internalstatements(newstatement);
@@ -412,9 +413,17 @@ implementation
{ a constructor needs a help procedure }
if (current_procinfo.procdef.proctypeoption=potype_constructor) then
begin
- if is_class(current_structdef) then
+ if is_class(current_structdef) or
+ (
+ is_objectpascal_helper(current_structdef) and
+ is_class(tobjectdef(current_structdef).extendeddef)
+ ) then
begin
- srsym:=search_struct_member(current_structdef,'NEWINSTANCE');
+ if is_objectpascal_helper(current_structdef) then
+ def:=tabstractrecorddef(tobjectdef(current_structdef).extendeddef)
+ else
+ def:=current_structdef;
+ srsym:=search_struct_member(def,'NEWINSTANCE');
if assigned(srsym) and
(srsym.typ=procsym) then
begin
@@ -882,6 +891,13 @@ implementation
end;
end;
+
+ const
+ exception_flags: array[boolean] of tprocinfoflags = (
+ [],
+ [pi_uses_exceptions,pi_needs_implicit_finally,pi_has_implicit_finally]
+ );
+
procedure tcgprocinfo.setup_tempgen;
begin
tg:=tgobjclass.create;
@@ -906,6 +922,9 @@ implementation
* incoming parameters on the stack
* open arrays
- no local variables
+
+ - stack frame cannot be optimized if using Win64 SEH
+ (at least with the current state of our codegenerator).
}
if ((po_assembler in procdef.procoptions) and
(m_delphi in current_settings.modeswitches) and
@@ -915,12 +934,13 @@ implementation
((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_is_assembler,
-{$ifdef i386}
- pi_uses_exceptions,pi_needs_implicit_finally,pi_has_implicit_finally,
-{$endif i386}
- pi_has_stackparameter,
- pi_needs_stackframe])=[])
+ ((flags*([pi_has_assembler_block,pi_is_assembler,
+ pi_has_stackparameter,pi_needs_stackframe]+
+ exception_flags[(target_info.cpu=cpu_i386)
+{$ifdef TEST_WIN64_SEH}
+ or (target_info.system=system_x86_64_win64)
+{$endif TEST_WIN64_SEH}
+ ]))=[])
)
then
begin
@@ -1473,7 +1493,7 @@ implementation
current_filepos:=exitpos;
hlcg.gen_proc_symbol_end(templist);
aktproccode.concatlist(templist);
-{$if defined(POWERPC) or defined(POWERPC64)}
+{$ifdef fpc_compiler_has_fixup_jmps}
fixup_jmps(aktproccode);
{$endif}
{ insert line debuginfo }
diff --git a/mips/compiler/psystem.pas b/mips/compiler/psystem.pas
index 6d86b4ba06..1cb59e0420 100644
--- a/mips/compiler/psystem.pas
+++ b/mips/compiler/psystem.pas
@@ -610,10 +610,11 @@ implementation
aiclass[ait_stab]:=tai_stab;
aiclass[ait_force_line]:=tai_force_line;
aiclass[ait_function_name]:=tai_function_name;
+ aiclass[ait_ent]:=tai_ent;
+ aiclass[ait_ent_end]:=tai_ent_end;
{$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}
diff --git a/mips/compiler/ptype.pas b/mips/compiler/ptype.pas
index 29319b7d28..cd747b1405 100644
--- a/mips/compiler/ptype.pas
+++ b/mips/compiler/ptype.pas
@@ -151,6 +151,20 @@ implementation
not(is_objcclass(ttypesym(srsym).typedef)) and
not(is_javaclass(ttypesym(srsym).typedef)) then
MessagePos1(def.typesym.fileinfo,type_e_class_type_expected,ttypesym(srsym).typedef.typename);
+ { this could also be a generic dummy that was not
+ overridden with a specific type }
+ if (sp_generic_dummy in srsym.symoptions) and
+ (
+ (ttypesym(srsym).typedef.typ=undefineddef) or
+ (
+ { or an unspecialized generic symbol, which is
+ the case for generics defined in non-Delphi
+ modes }
+ (df_generic in ttypesym(srsym).typedef.defoptions) and
+ not parse_generic
+ )
+ ) then
+ MessagePos(def.typesym.fileinfo,parser_e_no_generics_as_types);
end
else
begin
@@ -425,8 +439,22 @@ implementation
if ([stoAllowSpecialization,stoAllowTypeDef] * options <> []) and
(m_delphi in current_settings.modeswitches) then
dospecialize:=token in [_LSHARPBRACKET,_LT];
+ if dospecialize and
+ (def.typ=forwarddef) then
+ begin
+ if not assigned(srsym) or not (srsym.typ=typesym) then
+ begin
+ Message(type_e_type_is_not_completly_defined);
+ def:=generrordef;
+ dospecialize:=false;
+ end;
+ end;
if dospecialize then
- generate_specialization(def,stoParseClassParent in options,'',nil,'')
+ begin
+ if def.typ=forwarddef then
+ def:=ttypesym(srsym).typedef;
+ generate_specialization(def,stoParseClassParent in options,'',nil,'');
+ end
else
begin
if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
@@ -775,6 +803,10 @@ implementation
if old_parse_generic then
include(current_structdef.defoptions, df_generic);
parse_generic:=(df_generic in current_structdef.defoptions);
+ { in non-Delphi modes we need a strict private symbol without type
+ count and type parameters in the name to simply resolving }
+ maybe_insert_generic_rename_symbol(n,genericlist);
+
if m_advanced_records in current_settings.modeswitches then
begin
parse_record_members;
@@ -1131,40 +1163,40 @@ implementation
begin
if pt.nodetype=rangen then
begin
- { check the expression only if we are not in a generic declaration }
- if not(parse_generic) then
+ { pure ordconstn expressions can be checked for
+ generics as well, but don't give an error in case
+ of parsing a generic if that isn't yet the case }
+ if (trangenode(pt).left.nodetype=ordconstn) and
+ (trangenode(pt).right.nodetype=ordconstn) then
begin
- if (trangenode(pt).left.nodetype=ordconstn) and
- (trangenode(pt).right.nodetype=ordconstn) then
+ { 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
- { 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
+ 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
- Message(type_e_cant_eval_constant_expr);
- end;
+ indexdef:=trangenode(pt).left.resultdef;
+ end
+ else
+ if not parse_generic then
+ Message(type_e_cant_eval_constant_expr);
end
else
Message(sym_e_error_in_type_def)
@@ -1312,6 +1344,7 @@ implementation
const
SingleTypeOptionsInTypeBlock:array[Boolean] of TSingleTypeOptions = ([],[stoIsForwardDef]);
+ SingleTypeOptionsIsDelphi:array[Boolean] of TSingleTypeOptions = ([],[stoAllowSpecialization]);
var
p : tnode;
hdef : tdef;
@@ -1441,7 +1474,17 @@ implementation
_CARET:
begin
consume(_CARET);
- single_type(tt2,SingleTypeOptionsInTypeBlock[block_type=bt_type]);
+ single_type(tt2,
+ SingleTypeOptionsInTypeBlock[block_type=bt_type]+
+ SingleTypeOptionsIsDelphi[m_delphi in current_settings.modeswitches]
+ );
+ { in case of e.g. var or const sections we need to especially
+ check that we don't use a generic dummy symbol }
+ if (block_type<>bt_type) and
+ (tt2.typ=undefineddef) and
+ assigned(tt2.typesym) and
+ (sp_generic_dummy in tt2.typesym.symoptions) then
+ Message(parser_e_no_generics_as_types);
{ don't use getpointerdef() here, since this is a type
declaration (-> must create new typedef) }
def:=tpointerdef.create(tt2);
diff --git a/mips/compiler/rautils.pas b/mips/compiler/rautils.pas
index d7c0999097..bc27d5a6ab 100644
--- a/mips/compiler/rautils.pas
+++ b/mips/compiler/rautils.pas
@@ -689,6 +689,7 @@ begin
if (not is_void(returndef)) then
begin
if (m_tp7 in current_settings.modeswitches) and
+ not (df_generic in defoptions) and
(not paramanager.ret_in_param(returndef,proccalloption)) then
begin
message(asmr_e_cannot_use_RESULT_here);
diff --git a/mips/compiler/rgobj.pas b/mips/compiler/rgobj.pas
index 70734179a5..0cd1f1aa63 100644
--- a/mips/compiler/rgobj.pas
+++ b/mips/compiler/rgobj.pas
@@ -1,5 +1,5 @@
{
- Copyright (c) 1998-2002 by Florian Klaempfl
+ Copyright (c) 1998-2012 by the Free Pascal team
This unit implements the base class for the register allocator
@@ -191,7 +191,8 @@ unit rgobj;
{# Highest register allocated until now.}
reginfo : PReginfo;
usable_registers_cnt : word;
- usable_registers : array[0..maxcpuregister-1] of tsuperregister;
+ usable_registers : array[0..maxcpuregister] of tsuperregister;
+ usable_register_set : tcpuregisterset;
ibitmap : Tinterferencebitmap;
spillednodes,
simplifyworklist,
@@ -399,7 +400,10 @@ unit rgobj;
// 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];
+ begin
+ usable_registers[i]:=Ausable[i];
+ include(usable_register_set,Ausable[i]);
+ end;
usable_registers_cnt:=high(Ausable)+1;
{ Initialize Worklists }
spillednodes.init;
@@ -996,6 +1000,7 @@ unit rgobj;
begin
ok:=(t<first_imaginary) or
+ ((r<first_imaginary) and (r in usable_register_set)) or
(reginfo[t].degree<usable_registers_cnt) or
ibitmap[r,t];
end;
@@ -1371,7 +1376,7 @@ unit rgobj;
n:=coalescednodes.buf^[i-1];
k:=get_alias(n);
reginfo[n].colour:=reginfo[k].colour;
- if reginfo[k].colour<maxcpuregister then
+ if reginfo[k].colour<first_imaginary then
include(used_in_proc,reginfo[k].colour);
end;
end;
@@ -1567,6 +1572,7 @@ unit rgobj;
p:=headertai;
while assigned(p) do
begin
+ prefetch(pointer(p.next)^);
if p.typ=ait_regalloc then
with Tai_regalloc(p) do
begin
@@ -1632,6 +1638,7 @@ unit rgobj;
p:=Tai(list.first);
while assigned(p) do
begin
+ prefetch(pointer(p.next)^);
case p.typ of
ait_regalloc:
with Tai_regalloc(p) do
@@ -1867,6 +1874,9 @@ unit rgobj;
ins:=spilling_create_load(spilltemp,tempreg);
add_cpu_interferences(ins);
list.insertafter(ins,pos);
+ {$ifdef DEBUG_SPILLING}
+ list.Insertbefore(tai_comment.Create(strpnew('XXX: Spill Read')),ins);
+ {$endif}
end;
@@ -1877,6 +1887,9 @@ unit rgobj;
ins:=spilling_create_store(tempreg,spilltemp);
add_cpu_interferences(ins);
list.insertafter(ins,pos);
+ {$ifdef DEBUG_SPILLING}
+ list.Insertbefore(tai_comment.Create(strpnew('XXX: Spill Write')),ins);
+ {$endif}
end;
diff --git a/mips/compiler/scanner.pas b/mips/compiler/scanner.pas
index 1fbec44792..5d9eac0050 100644
--- a/mips/compiler/scanner.pas
+++ b/mips/compiler/scanner.pas
@@ -174,9 +174,16 @@ interface
procedure stoprecordtokens;
procedure replaytoken;
procedure startreplaytokens(buf:tdynamicarray; achange_endian : boolean);
- { bit length sizeint is target depend }
- procedure tokenwritesizeint(val : sizeint);
- function tokenreadsizeint : sizeint;
+ { bit length asizeint is target depend }
+ procedure tokenwritesizeint(val : asizeint);
+ procedure tokenwritelongint(val : longint);
+ procedure tokenwritelongword(val : longword);
+ procedure tokenwriteword(val : word);
+ procedure tokenwriteshortint(val : shortint);
+ procedure tokenwriteset(var b;size : longint);
+ procedure tokenwriteenum(var b;size : longint);
+ function tokenreadsizeint : asizeint;
+ procedure tokenwritesettings(var asettings : tsettings; var size : asizeint);
{ longword/longint are 32 bits on all targets }
{ word/smallint are 16-bits on all targest }
function tokenreadlongword : longword;
@@ -190,7 +197,7 @@ interface
procedure tokenreadset(var b;size : longint);
function tokenreadenum(size : longint) : longword;
- procedure tokenreadsettings(var asettings : tsettings; expected_size : longint);
+ procedure tokenreadsettings(var asettings : tsettings; expected_size : asizeint);
procedure readchar;
procedure readstring;
procedure readnumber;
@@ -2177,16 +2184,36 @@ In case not, the value returned can be arbitrary.
recordtokenbuf.write(b,1);
end;
- procedure tscannerfile.tokenwritesizeint(val : sizeint);
+ procedure tscannerfile.tokenwritesizeint(val : asizeint);
begin
- recordtokenbuf.write(val,sizeof(sizeint));
+ recordtokenbuf.write(val,sizeof(asizeint));
end;
- function tscannerfile.tokenreadsizeint : sizeint;
+ procedure tscannerfile.tokenwritelongint(val : longint);
+ begin
+ recordtokenbuf.write(val,sizeof(longint));
+ end;
+
+ procedure tscannerfile.tokenwriteshortint(val : shortint);
+ begin
+ recordtokenbuf.write(val,sizeof(shortint));
+ end;
+
+ procedure tscannerfile.tokenwriteword(val : word);
+ begin
+ recordtokenbuf.write(val,sizeof(word));
+ end;
+
+ procedure tscannerfile.tokenwritelongword(val : longword);
+ begin
+ recordtokenbuf.write(val,sizeof(longword));
+ end;
+
+ function tscannerfile.tokenreadsizeint : asizeint;
var
- val : sizeint;
+ val : asizeint;
begin
- replaytokenbuf.read(val,sizeof(sizeint));
+ replaytokenbuf.read(val,sizeof(asizeint));
if tokenbuf_change_endian then
val:=swapendian(val);
result:=val;
@@ -2268,8 +2295,18 @@ In case not, the value returned can be arbitrary.
Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
end;
+ procedure tscannerfile.tokenwriteenum(var b;size : longint);
+ begin
+ recordtokenbuf.write(b,size);
+ end;
+
+ procedure tscannerfile.tokenwriteset(var b;size : longint);
+ begin
+ recordtokenbuf.write(b,size);
+ end;
- procedure tscannerfile.tokenreadsettings(var asettings : tsettings; expected_size : longint);
+
+ procedure tscannerfile.tokenreadsettings(var asettings : tsettings; expected_size : asizeint);
{ This procedure
needs to be changed whenever
@@ -2337,12 +2374,84 @@ In case not, the value returned can be arbitrary.
end;
end;
+ procedure tscannerfile.tokenwritesettings(var asettings : tsettings; var size : asizeint);
+
+ { 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
+ sizepos, startpos, endpos : longword;
+ begin
+ { WARNING all those fields need to be in the correct
+ order otherwise cross_endian PPU reading will fail }
+ sizepos:=recordtokenbuf.pos;
+ size:=0;
+ tokenwritesizeint(size);
+ startpos:=recordtokenbuf.pos;
+ with asettings do
+ begin
+ tokenwritelongint(alignment.procalign);
+ tokenwritelongint(alignment.loopalign);
+ tokenwritelongint(alignment.jumpalign);
+ tokenwritelongint(alignment.constalignmin);
+ tokenwritelongint(alignment.constalignmax);
+ tokenwritelongint(alignment.varalignmin);
+ tokenwritelongint(alignment.varalignmax);
+ tokenwritelongint(alignment.localalignmin);
+ tokenwritelongint(alignment.localalignmax);
+ tokenwritelongint(alignment.recordalignmin);
+ tokenwritelongint(alignment.recordalignmax);
+ tokenwritelongint(alignment.maxCrecordalign);
+ tokenwriteset(globalswitches,sizeof(globalswitches));
+ tokenwriteset(targetswitches,sizeof(targetswitches));
+ tokenwriteset(moduleswitches,sizeof(moduleswitches));
+ tokenwriteset(localswitches,sizeof(localswitches));
+ tokenwriteset(modeswitches,sizeof(modeswitches));
+ tokenwriteset(optimizerswitches,sizeof(optimizerswitches));
+ tokenwriteset(genwpoptimizerswitches,sizeof(genwpoptimizerswitches));
+ tokenwriteset(dowpoptimizerswitches,sizeof(dowpoptimizerswitches));
+ tokenwriteset(debugswitches,sizeof(debugswitches));
+ { 0: old behaviour for sets <=256 elements
+ >0: round to this size }
+ tokenwriteshortint(setalloc);
+ tokenwriteshortint(packenum);
+ tokenwriteshortint(packrecords);
+ tokenwriteshortint(maxfpuregisters);
+
+ tokenwriteenum(cputype,sizeof(tcputype));
+ tokenwriteenum(optimizecputype,sizeof(tcputype));
+ tokenwriteenum(fputype,sizeof(tfputype));
+ tokenwriteenum(asmmode,sizeof(tasmmode));
+ tokenwriteenum(interfacetype,sizeof(tinterfacetypes));
+ tokenwriteenum(defproccall,sizeof(tproccalloption));
+ { tstringencoding is word type,
+ thus this should be OK here }
+ tokenwriteword(sourcecodepage);
+
+ tokenwriteenum(minfpconstprec,sizeof(tfloattype));
+
+ recordtokenbuf.write(byte(disabledircache),1);
+{$if defined(ARM) or defined(AVR)}
+ tokenwriteenum(controllertype,sizeof(tcontrollertype));
+{$endif defined(ARM) or defined(AVR)}
+ endpos:=recordtokenbuf.pos;
+ size:=endpos-startpos;
+ recordtokenbuf.seek(sizepos);
+ tokenwritesizeint(size);
+ recordtokenbuf.seek(endpos);
+ end;
+ end;
+
procedure tscannerfile.recordtoken;
var
t : ttoken;
s : tspecialgenerictoken;
- len,val,msgnb,copy_size : sizeint;
+ len,msgnb,copy_size : asizeint;
+ val : longint;
b : byte;
pmsg : pmessagestaterecord;
begin
@@ -2360,8 +2469,7 @@ In case not, the value returned can be arbitrary.
writetoken(t);
recordtokenbuf.write(s,1);
copy_size:=sizeof(current_settings)-sizeof(pointer);
- tokenwritesizeint(copy_size);
- recordtokenbuf.write(current_settings,copy_size);
+ tokenwritesettings(current_settings,copy_size);
last_settings:=current_settings;
end;
@@ -2375,7 +2483,7 @@ In case not, the value returned can be arbitrary.
pmsg:=current_settings.pmessage;
while assigned(pmsg) do
begin
- if msgnb=high(sizeint) then
+ if msgnb=high(asizeint) then
{ Too many messages }
internalerror(2011090401);
inc(msgnb);
@@ -2385,11 +2493,12 @@ In case not, the value returned can be arbitrary.
pmsg:=current_settings.pmessage;
while assigned(pmsg) do
begin
- { What about endianess here? }
+ { What about endianess here?}
+ { SB: this is handled by tokenreadlongint }
val:=pmsg^.value;
- tokenwritesizeint(val);
+ tokenwritelongint(val);
val:=ord(pmsg^.state);
- tokenwritesizeint(val);
+ tokenwritelongint(val);
pmsg:=pmsg^.next;
end;
last_message:=current_settings.pmessage;
@@ -2506,7 +2615,7 @@ In case not, the value returned can be arbitrary.
procedure tscannerfile.replaytoken;
var
- wlen,mesgnb,copy_size : sizeint;
+ wlen,mesgnb,copy_size : asizeint;
specialtoken : tspecialgenerictoken;
i : byte;
pmsg,prevmsg : pmessagestaterecord;
@@ -2575,11 +2684,6 @@ In case not, the value returned can be arbitrary.
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
@@ -2587,8 +2691,8 @@ In case not, the value returned can be arbitrary.
ST_LOADSETTINGS:
begin
copy_size:=tokenreadsizeint;
- if copy_size <> sizeof(current_settings)-sizeof(pointer) then
- internalerror(2011090501);
+ //if copy_size <> sizeof(current_settings)-sizeof(pointer) then
+ // internalerror(2011090501);
{
replaytokenbuf.read(current_settings,copy_size);
}
@@ -2610,8 +2714,8 @@ In case not, the value returned can be arbitrary.
end
else
prevmsg^.next:=pmsg;
- replaytokenbuf.read(pmsg^.value,sizeof(longint));
- replaytokenbuf.read(pmsg^.state,sizeof(tmsgstate));
+ pmsg^.value:=tokenreadlongint;
+ pmsg^.state:=tmsgstate(tokenreadlongint);
pmsg^.next:=nil;
prevmsg:=pmsg;
end;
@@ -2619,32 +2723,16 @@ In case not, the value returned can be arbitrary.
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
diff --git a/mips/compiler/sparc/cgcpu.pas b/mips/compiler/sparc/cgcpu.pas
index 4da36945d7..87f232a891 100644
--- a/mips/compiler/sparc/cgcpu.pas
+++ b/mips/compiler/sparc/cgcpu.pas
@@ -1177,10 +1177,10 @@ implementation
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);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,ptrsinttype,paraloc3);
+ a_load_const_cgpara(list,OS_SINT,len,paraloc3);
a_loadaddr_ref_cgpara(list,dest,paraloc2);
a_loadaddr_ref_cgpara(list,source,paraloc1);
paramanager.freecgpara(list,paraloc3);
diff --git a/mips/compiler/sparc/cpubase.pas b/mips/compiler/sparc/cpubase.pas
index d07eeebbf0..880b0be023 100644
--- a/mips/compiler/sparc/cpubase.pas
+++ b/mips/compiler/sparc/cpubase.pas
@@ -249,10 +249,10 @@ uses
This value can be deduced from CALLED_USED_REGISTERS array in the
GCC source.
}
- saved_standard_registers : array[0..0] of tsuperregister = (RS_NO);
+ saved_standard_registers : array[0..0] of tsuperregister = (RS_INVALID);
{ this is only for the generic code which is not used for this architecture }
- saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+ 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
diff --git a/mips/compiler/sparc/cpupara.pas b/mips/compiler/sparc/cpupara.pas
index aca3bec939..30046ccc4f 100644
--- a/mips/compiler/sparc/cpupara.pas
+++ b/mips/compiler/sparc/cpupara.pas
@@ -38,7 +38,7 @@ interface
{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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -75,16 +75,17 @@ implementation
end;
- procedure TSparcParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
+ procedure TSparcParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
begin
if nr<1 then
InternalError(2002100806);
cgpara.reset;
- cgpara.size:=OS_ADDR;
- cgpara.intsize:=sizeof(pint);
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=std_param_align;
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -150,38 +151,8 @@ implementation
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;
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
paraloc:=result.add_location;
{ Return in FPU register? }
@@ -235,6 +206,7 @@ implementation
paraloc : pcgparalocation;
i : integer;
hp : tparavarsym;
+ paradef : tdef;
paracgsize : tcgsize;
hparasupregs : pparasupregs;
paralen : longint;
@@ -246,10 +218,11 @@ implementation
for i:=0 to paras.count-1 do
begin
hp:=tparavarsym(paras[i]);
+ paradef:=hp.vardef;
{ 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
+ is_array_of_const(paradef) then
begin
paraloc:=hp.paraloc[side].add_location;
{ hack: the paraloc must be valid, but is not actually used }
@@ -259,20 +232,28 @@ implementation
break;
end;
- if push_addr_param(hp.varspez,hp.vardef,p.proccalloption) then
- paracgsize:=OS_ADDR
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ begin
+ paracgsize:=OS_ADDR;
+ paradef:=getpointerdef(paradef);
+ end
else
begin
- paracgsize:=def_cgSize(hp.vardef);
+ paracgsize:=def_cgsize(paradef);
+ { for formaldef }
if paracgsize=OS_NO then
- paracgsize:=OS_ADDR;
+ begin
+ paracgsize:=OS_ADDR;
+ paradef:=voidpointertype;
+ end;
end;
hp.paraloc[side].reset;
hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].def:=paradef;
if (side = callerside) then
hp.paraloc[side].Alignment:=std_param_align
else
- hp.paraloc[side].Alignment:=hp.vardef.alignment;
+ hp.paraloc[side].Alignment:=paradef.alignment;
paralen:=tcgsize2size[paracgsize];
hp.paraloc[side].intsize:=paralen;
while paralen>0 do
diff --git a/mips/compiler/symdef.pas b/mips/compiler/symdef.pas
index 45f2f5891a..a6d6ca874c 100644
--- a/mips/compiler/symdef.pas
+++ b/mips/compiler/symdef.pas
@@ -635,6 +635,10 @@ interface
{$ifdef i386}
fpu_used : byte;
{$endif i386}
+{$ifdef mips}
+ { needed for stabs debugging }
+ total_local_size : longint;
+{$endif mips}
visibility : tvisibility;
{ set to a value different from tsk_none in case this procdef is for
a routine that has to be internally generated by the compiler }
diff --git a/mips/compiler/symtable.pas b/mips/compiler/symtable.pas
index 2d5dfc4978..627c01ddc8 100644
--- a/mips/compiler/symtable.pas
+++ b/mips/compiler/symtable.pas
@@ -2402,6 +2402,8 @@ implementation
hashedid : THashedIDString;
orgclass : tobjectdef;
i : longint;
+ hlpsrsym : tsym;
+ hlpsrsymtable : tsymtable;
begin
orgclass:=classh;
{ in case this is a formal class, first find the real definition }
@@ -2454,11 +2456,13 @@ implementation
end
else
begin
+ hlpsrsym:=nil;
+ hlpsrsymtable:=nil;
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
+ Pascal class and we haven't yet found a helper symbol }
+ if is_class(classh) and searchhelper and not assigned(hlpsrsym) then
begin
result:=search_objectpascal_helper(classh,contextclassh,s,srsym,srsymtable);
if result then
@@ -2467,7 +2471,14 @@ implementation
searching for overloads }
if (srsym.typ<>procsym) or
not (sp_has_overloaded in tprocsym(srsym).symoptions) then
- exit;
+ exit
+ else
+ begin
+ { remember the found symbol if the class hierarchy
+ should not contain the a method with that name }
+ hlpsrsym:=srsym;
+ hlpsrsymtable:=srsymtable;
+ end;
end;
srsymtable:=classh.symtable;
srsym:=tsym(srsymtable.FindWithHash(hashedid));
@@ -2480,6 +2491,15 @@ implementation
end;
classh:=classh.childof;
end;
+ { did we find a helper symbol, but no symbol with the same name in
+ the extended object's hierarchy? }
+ if assigned(hlpsrsym) then
+ begin
+ srsym:=hlpsrsym;
+ srsymtable:=hlpsrsymtable;
+ result:=true;
+ exit;
+ end;
end;
if is_objcclass(orgclass) then
result:=search_objc_helper(orgclass,s,srsym,srsymtable)
@@ -2493,8 +2513,12 @@ implementation
function searchsym_in_record(recordh:tabstractrecorddef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
var
hashedid : THashedIDString;
+ hlpsrsym : tsym;
+ hlpsrsymtable : tsymtable;
begin
result:=false;
+ hlpsrsym:=nil;
+ hlpsrsymtable:=nil;
hashedid.id:=s;
{ search for a record helper method first }
result:=search_objectpascal_helper(recordh,recordh,s,srsym,srsymtable);
@@ -2504,7 +2528,14 @@ implementation
searching for overloads }
if (srsym.typ<>procsym) or
not (sp_has_overloaded in tprocsym(srsym).symoptions) then
- exit;
+ exit
+ else
+ begin
+ { remember the found symbol if we should not find a symbol with
+ the same name in the extended record }
+ hlpsrsym:=srsym;
+ hlpsrsymtable:=srsymtable;
+ end;
srsymtable:=recordh.symtable;
srsym:=tsym(srsymtable.FindWithHash(hashedid));
if assigned(srsym) and is_visible_for_object(srsym,recordh) then
@@ -2513,8 +2544,9 @@ implementation
result:=true;
exit;
end;
- srsym:=nil;
- srsymtable:=nil;
+ srsym:=hlpsrsym;
+ srsymtable:=hlpsrsymtable;
+ result:=assigned(srsym);
end;
function searchsym_in_class_by_msgint(classh:tobjectdef;msgid:longint;out srdef : tdef;out srsym:tsym;out srsymtable:TSymtable):boolean;
diff --git a/mips/compiler/systems/i_linux.pas b/mips/compiler/systems/i_linux.pas
index cfd4c4f3a8..92e3ffa021 100644
--- a/mips/compiler/systems/i_linux.pas
+++ b/mips/compiler/systems/i_linux.pas
@@ -966,11 +966,11 @@ initialization
set_source_info(system_arm_linux_info);
{$endif linux}
{$endif CPUARM}
-{$ifdef CPUMIPS}
+{$ifdef CPUMIPSEB}
{$ifdef linux}
set_source_info(system_mipseb_linux_info);
{$endif linux}
-{$endif CPUMIPS}
+{$endif CPUMIPSEB}
{$ifdef CPUMIPSEL}
{$ifdef linux}
set_source_info(system_mipsel_linux_info);
diff --git a/mips/compiler/systems/t_go32v2.pas b/mips/compiler/systems/t_go32v2.pas
index 831611ae11..6a95d72347 100644
--- a/mips/compiler/systems/t_go32v2.pas
+++ b/mips/compiler/systems/t_go32v2.pas
@@ -164,7 +164,7 @@ implementation
Concat(' OBJSECTION .stabstr');
Concat('ENDEXESECTION');
{ DWARF 2 }
- ConcatGenericSections('.debug_aranges,.debug_pubnames,.debug_info,.debug_abbrev,'+
+ ScriptAddGenericSections('.debug_aranges,.debug_pubnames,.debug_info,.debug_abbrev,'+
'.debug_line,.debug_frame,.debug_str,.debug_loc,.debug_macinfo');
Concat('STABS');
Concat('SYMBOLS');
diff --git a/mips/compiler/systems/t_linux.pas b/mips/compiler/systems/t_linux.pas
index 75ec90b091..b27e326a6f 100644
--- a/mips/compiler/systems/t_linux.pas
+++ b/mips/compiler/systems/t_linux.pas
@@ -40,11 +40,11 @@ interface
procedure setfininame(list: TAsmList; const s: string); override;
end;
+ TLibcType=(libc5,glibc2,glibc21,uclibc);
+
tlinkerlinux=class(texternallinker)
private
- libctype:(libc5,glibc2,glibc21,uclibc);
- cprtobj,
- gprtobj,
+ libctype: TLibcType;
prtobj : string[80];
reorder : boolean;
linklibc: boolean;
@@ -108,9 +108,8 @@ implementation
TLINKERLINUX
*****************************************************************************}
-Constructor TLinkerLinux.Create;
+procedure SetupLibrarySearchPath;
begin
- Inherited Create;
if not Dontlinkstdlibpath Then
{$ifdef x86_64}
LibrarySearchPath.AddPath(sysrootpath,'/lib64;/usr/lib64;/usr/X11R6/lib64',true);
@@ -123,128 +122,151 @@ begin
{$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';
+ { experimental, is this correct? }
+ const defdynlinker='/lib/ld-linux.so.2';
{$endif m68k}
{$ifdef i386}
- defdynlinker:='/lib/ld-linux.so.2';
+ const defdynlinker='/lib/ld-linux.so.2';
{$endif}
{$ifdef x86_64}
- defdynlinker:='/lib64/ld-linux-x86-64.so.2';
+ const defdynlinker='/lib64/ld-linux-x86-64.so.2';
{$endif x86_64}
{$ifdef sparc}
- defdynlinker:='/lib/ld-linux.so.2';
+ const defdynlinker='/lib/ld-linux.so.2';
{$endif sparc}
{$ifdef powerpc}
- defdynlinker:='/lib/ld.so.1';
+ const defdynlinker='/lib/ld.so.1';
{$endif powerpc}
{$ifdef powerpc64}
- defdynlinker:='/lib64/ld64.so.1';
+ const defdynlinker='/lib64/ld64.so.1';
{$endif powerpc64}
{$ifdef arm}
{$ifdef FPC_ARMHF}
- defdynlinker:='/lib/arm-linux-gnueabihf/ld-linux.so.3';
+ const defdynlinker='/lib/arm-linux-gnueabihf/ld-linux.so.3';
{$else FPC_ARMHF}
{$ifdef FPC_ARMEL}
- defdynlinker:='/lib/ld-linux.so.3';
+ const defdynlinker='/lib/ld-linux.so.3';
{$else FPC_ARMEL}
- defdynlinker:='/lib/ld-linux.so.2';
+ const defdynlinker='/lib/ld-linux.so.2';
{$endif FPC_ARMEL}
{$endif FPC_ARMHF}
{$endif arm}
{$ifdef mips}
- defdynlinker:='/lib/ld.so.1';
+ const 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;
+
+procedure SetupDynlinker(out DynamicLinker:string;out libctype:TLibcType);
+begin
+ {
+ 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;
+ libctype:=glibc21;
{$else i386}
- libctype:=glibc2;
+ 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
+ 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
+ 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
- }
+ 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;
+ libctype:=glibc21;
{$else i386}
- libctype:=glibc2;
+ libctype:=glibc2;
{$endif i386}
- end;
+ end;
+end;
+
+function ModulesLinkToLibc:boolean;
+var
+ hp: tmodule;
+begin
+ result:=false;
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ result:=hp.linkothersharedlibs.find('c');
+ if result then break;
+ hp:=tmodule(hp.next);
+ end;
+end;
+
+Constructor TLinkerLinux.Create;
+begin
+ Inherited Create;
+ SetupLibrarySearchPath;
+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}
+
+
+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';
+
+ SetupDynlinker(DynamicLinker,libctype);
end;
end;
@@ -263,70 +285,39 @@ Begin
end;
End;
+type
+ tlibcnames=array [TLibcType] of string[8];
+
+const { libc5 glibc2 glibc21 uclibc }
+ cprtnames: tlibcnames = ('cprt0', 'cprt0', 'cprt21', 'ucprt0');
+ csinames: tlibcnames = ('si_c', 'si_c', 'si_c21', 'si_uc');
+ gprtnames: tlibcnames = ('gprt0', 'gprt0', 'gprt21', 'ugprt0');
+ gsinames: tlibcnames = ('si_g', 'si_g', 'si_c21g','si_ucg');
+
+ defprtnames: array[boolean] of string[8] = ('prt0', 'dllprt0');
+ defsinames: array[boolean] of string[8] = ('si_prc','si_dll');
+
+{ uclibc and glibc21 are not available on x86_64! si_g is also absent. }
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;
+ linklibc:=ModulesLinkToLibc;
+ reorder:=linklibc and ReOrderEntries;
+ sysinitunit:=defsinames[current_module.islibrary];
+ prtobj:=defprtnames[current_module.islibrary];
+
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;
+ exit;
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;
+ begin
+ prtobj:=gprtnames[libctype];
+ sysinitunit:=gsinames[libctype];
+ linklibc:=true;
+ end
+ else if linklibc then
+ begin
+ prtobj:=cprtnames[libctype];
+ sysinitunit:=csinames[libctype];
+ end;
end;
Function TLinkerLinux.WriteResponseFile(isdll:boolean) : Boolean;
diff --git a/mips/compiler/systems/t_win.pas b/mips/compiler/systems/t_win.pas
index 11dde31245..b43cd6442f 100644
--- a/mips/compiler/systems/t_win.pas
+++ b/mips/compiler/systems/t_win.pas
@@ -939,31 +939,10 @@ implementation
procedure TInternalLinkerWin.DefaultLinkScript;
- var
- s,s2 : TCmdStr;
begin
+ ScriptAddSourceStatements(true);
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;
@@ -1079,7 +1058,7 @@ implementation
Concat(' OBJSECTION .idata$6*');
Concat(' OBJSECTION .idata$7*');
Concat('ENDEXESECTION');
- ConcatGenericSections('.edata,.rsrc,.reloc,.gnu_debuglink,'+
+ ScriptAddGenericSections('.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');
{ Can't use the generic rules, because that will add also .stabstr to .stab }
diff --git a/mips/compiler/utils/Makefile b/mips/compiler/utils/Makefile
index e0d3110da2..a7db00e717 100644
--- a/mips/compiler/utils/Makefile
+++ b/mips/compiler/utils/Makefile
@@ -1,8 +1,8 @@
#
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/04/25]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/06/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 powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mipseb-linux mipsel-linux jvm-java jvm-android
+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 powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux jvm-java jvm-android
BSDs = freebsd netbsd openbsd darwin
UNIXs = linux $(BSDs) solaris qnx haiku aix
LIMIT83fs = go32v2 os2 emx watcom
@@ -492,7 +492,7 @@ endif
ifeq ($(FULL_TARGET),armeb-embedded)
override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
endif
-ifeq ($(FULL_TARGET),mipseb-linux)
+ifeq ($(FULL_TARGET),mips-linux)
override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
endif
ifeq ($(FULL_TARGET),mipsel-linux)
@@ -702,7 +702,7 @@ endif
ifeq ($(FULL_TARGET),armeb-embedded)
override CLEAN_UNITS+=ppu crc usubst
endif
-ifeq ($(FULL_TARGET),mipseb-linux)
+ifeq ($(FULL_TARGET),mips-linux)
override CLEAN_UNITS+=ppu crc usubst
endif
ifeq ($(FULL_TARGET),mipsel-linux)
@@ -913,7 +913,7 @@ endif
ifeq ($(FULL_TARGET),armeb-embedded)
override COMPILER_UNITDIR+=..
endif
-ifeq ($(FULL_TARGET),mipseb-linux)
+ifeq ($(FULL_TARGET),mips-linux)
override COMPILER_UNITDIR+=..
endif
ifeq ($(FULL_TARGET),mipsel-linux)
@@ -1123,7 +1123,7 @@ endif
ifeq ($(FULL_TARGET),armeb-embedded)
override COMPILER_SOURCEDIR+=..
endif
-ifeq ($(FULL_TARGET),mipseb-linux)
+ifeq ($(FULL_TARGET),mips-linux)
override COMPILER_SOURCEDIR+=..
endif
ifeq ($(FULL_TARGET),mipsel-linux)
@@ -1946,7 +1946,7 @@ endif
ifeq ($(FULL_TARGET),armeb-embedded)
REQUIRE_PACKAGES_RTL=1
endif
-ifeq ($(FULL_TARGET),mipseb-linux)
+ifeq ($(FULL_TARGET),mips-linux)
REQUIRE_PACKAGES_RTL=1
endif
ifeq ($(FULL_TARGET),mipsel-linux)
@@ -2108,17 +2108,12 @@ 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
diff --git a/mips/compiler/utils/fpc.pp b/mips/compiler/utils/fpc.pp
index 4108b8e479..a6502f34c9 100644
--- a/mips/compiler/utils/fpc.pp
+++ b/mips/compiler/utils/fpc.pp
@@ -155,6 +155,15 @@ program fpc;
ppcbin:='ppcx64';
processorname:='x86_64';
{$endif x86_64}
+{$ifdef mipsel}
+ ppcbin:='ppcmipsel';
+ processorname:='mipsel';
+{$else : not mipsel}
+ {$ifdef mips}
+ ppcbin:='ppcmips';
+ processorname:='mips';
+ {$endif mips}
+{$endif not mipsel}
versionstr:=''; { Default is just the name }
if ParamCount = 0 then
begin
@@ -201,8 +210,8 @@ program fpc;
cpusuffix:='386'
else if processorstr='m68k' then
cpusuffix:='68k'
- else if processorstr='mipseb' then
- cpusuffix:='mipseb'
+ else if processorstr='mips' then
+ cpusuffix:='mips'
else if processorstr='mipsel' then
cpusuffix:='mipsel'
else if processorstr='powerpc' then
diff --git a/mips/compiler/verbose.pas b/mips/compiler/verbose.pas
index 12f013ef60..a3ebef5e91 100644
--- a/mips/compiler/verbose.pas
+++ b/mips/compiler/verbose.pas
@@ -512,11 +512,35 @@ implementation
i:=j-1;
end;
'w','W' :
- status.errorwarning:=true;
+ begin
+ if (i<length(s)) and (s[i+1]='-') then
+ begin
+ inc(i);
+ status.errorwarning:=false;
+ end
+ else
+ status.errorwarning:=true;
+ end;
'n','N' :
- status.errornote:=true;
+ begin
+ if (i<length(s)) and (s[i+1]='-') then
+ begin
+ inc(i);
+ status.errornote:=false;
+ end
+ else
+ status.errornote:=true;
+ end;
'h','H' :
- status.errorhint:=true;
+ begin
+ if (i<length(s)) and (s[i+1]='-') then
+ begin
+ inc(i);
+ status.errorhint:=false;
+ end
+ else
+ status.errorhint:=true;
+ end;
end;
end;
end;
diff --git a/mips/compiler/version.pas b/mips/compiler/version.pas
index 0faa32d813..2d8198405a 100644
--- a/mips/compiler/version.pas
+++ b/mips/compiler/version.pas
@@ -72,7 +72,7 @@ interface
source_cpu_string = 'arm';
{$endif cpuarm}
{$ifdef cpumipseb}
- source_cpu_string = 'mipseb';
+ source_cpu_string = 'mips'{'mipseb'};
{$endif cpumipseb}
{$ifdef cpumipsel}
source_cpu_string = 'mipsel';
diff --git a/mips/compiler/x86/aasmcpu.pas b/mips/compiler/x86/aasmcpu.pas
index dc7d7cee8a..ce1f95e493 100644
--- a/mips/compiler/x86/aasmcpu.pas
+++ b/mips/compiler/x86/aasmcpu.pas
@@ -1038,8 +1038,11 @@ implementation
begin
currsym:=objdata.symbolref(ref^.symbol);
l:=ref^.offset;
+{$push}
+{$r-}
if assigned(currsym) then
inc(l,currsym.address);
+{$pop}
{ 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
@@ -2212,8 +2215,11 @@ implementation
begin
getvalsym(c-40);
data:=currval-insend;
+{$push}
+{$r-}
if assigned(currsym) then
inc(data,currsym.address);
+{$pop}
if (data>127) or (data<-128) then
Message1(asmw_e_short_jmp_out_of_range,tostr(data));
objdata.writebytes(data,1);
diff --git a/mips/compiler/x86/agx86int.pas b/mips/compiler/x86/agx86int.pas
index be4cdbe50f..05c9d3ab27 100644
--- a/mips/compiler/x86/agx86int.pas
+++ b/mips/compiler/x86/agx86int.pas
@@ -902,7 +902,7 @@ implementation
hal : tasmlisttype;
begin
{$ifdef EXTDEBUG}
- if assigned(current_module.mainsource) then
+ if 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
@@ -943,7 +943,7 @@ implementation
AsmLn;
{$ifdef EXTDEBUG}
- if assigned(current_module.mainsource) then
+ if current_module.mainsource<>'' then
comment(v_info,'Done writing intel-styled assembler output for '+current_module.mainsource);
{$endif EXTDEBUG}
end;
diff --git a/mips/compiler/x86/agx86nsm.pas b/mips/compiler/x86/agx86nsm.pas
index 365900910f..43f5f68408 100644
--- a/mips/compiler/x86/agx86nsm.pas
+++ b/mips/compiler/x86/agx86nsm.pas
@@ -1015,7 +1015,7 @@ interface
hal : tasmlisttype;
begin
{$ifdef EXTDEBUG}
- if assigned(current_module.mainsource) then
+ if current_module.mainsource<>'' then
comment(v_info,'Start writing nasm-styled assembler output for '+current_module.mainsource);
{$endif}
AsmWriteLn('BITS 32');
@@ -1037,7 +1037,7 @@ interface
FreeExternChainList;
end;
{$ifdef EXTDEBUG}
- if assigned(current_module.mainsource) then
+ if current_module.mainsource<>'' then
comment(v_info,'Done writing nasm-styled assembler output for '+current_module.mainsource);
{$endif EXTDEBUG}
end;
diff --git a/mips/compiler/x86/cgx86.pas b/mips/compiler/x86/cgx86.pas
index e9d4483879..2c5f2ce3b4 100644
--- a/mips/compiler/x86/cgx86.pas
+++ b/mips/compiler/x86/cgx86.pas
@@ -266,6 +266,8 @@ unit cgx86;
procedure tcgx86.inc_fpu_stack;
begin
+ if rgfpu.fpuvaroffset>=7 then
+ internalerror(2012062901);
inc(rgfpu.fpuvaroffset);
end;
diff --git a/mips/compiler/x86/cpubase.pas b/mips/compiler/x86/cpubase.pas
index 056e571cf7..6b300e1597 100644
--- a/mips/compiler/x86/cpubase.pas
+++ b/mips/compiler/x86/cpubase.pas
@@ -65,9 +65,6 @@ uses
*****************************************************************************}
const
- { Invalid register number }
- RS_INVALID = $ff;
-
{ Integer Super registers }
RS_RAX = $00; {EAX}
RS_RCX = $01; {ECX}
diff --git a/mips/compiler/x86/nx86inl.pas b/mips/compiler/x86/nx86inl.pas
index c609b332ce..b08ca6d007 100644
--- a/mips/compiler/x86/nx86inl.pas
+++ b/mips/compiler/x86/nx86inl.pas
@@ -271,6 +271,7 @@ implementation
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);
+ tcgx86(cg).dec_fpu_stack;
emit_none(A_FWAIT,S_NO);
end;
end;
@@ -306,6 +307,7 @@ implementation
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);
+ tcgx86(cg).dec_fpu_stack;
end
else
begin
@@ -319,6 +321,7 @@ implementation
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);
+ tcgx86(cg).dec_fpu_stack;
emit_ref(A_FLDCW,S_NO,oldcw);
emit_none(A_FWAIT,S_NO);
tg.UnGetTemp(current_asmdata.CurrAsmList,oldcw);
diff --git a/mips/compiler/x86_64/cgcpu.pas b/mips/compiler/x86_64/cgcpu.pas
index 8c20107361..99f52b54ca 100644
--- a/mips/compiler/x86_64/cgcpu.pas
+++ b/mips/compiler/x86_64/cgcpu.pas
@@ -298,8 +298,8 @@ unit cgcpu;
end;
para1.init;
para2.init;
- paramanager.getintparaloc(pocall_default,1,para1);
- paramanager.getintparaloc(pocall_default,2,para2);
+ paramanager.getintparaloc(pocall_default,1,voidpointertype,para1);
+ paramanager.getintparaloc(pocall_default,2,voidpointertype,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) }
diff --git a/mips/compiler/x86_64/cpupara.pas b/mips/compiler/x86_64/cpupara.pas
index bf785edcfa..eaf74d49cf 100644
--- a/mips/compiler/x86_64/cpupara.pas
+++ b/mips/compiler/x86_64/cpupara.pas
@@ -42,7 +42,7 @@ unit cpupara;
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;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; 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;
@@ -742,14 +742,15 @@ unit cpupara;
end;
- procedure tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ procedure tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
var
paraloc : pcgparalocation;
begin
cgpara.reset;
- cgpara.size:=OS_ADDR;
- cgpara.intsize:=sizeof(pint);
+ cgpara.size:=def_cgsize(def);
+ cgpara.intsize:=tcgsize2size[cgpara.size];
cgpara.alignment:=get_para_align(calloption);
+ cgpara.def:=def;
paraloc:=cgpara.add_location;
with paraloc^ do
begin
@@ -809,46 +810,18 @@ unit cpupara;
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
+ if set_common_funcretloc_info(p,def,retcgsize,result) then
+ exit;
+
+ { 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
- paraloc:=result.add_location;
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.size:=retcgsize;
- exit;
+ retcgsize:=OS_S32;
+ result.def:=s32inttype;
+ result.intsize:=4;
+ result.size:=retcgsize;
end;
{ Return in FPU register? -> don't use classify_argument(), because
@@ -961,6 +934,7 @@ unit cpupara;
var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
var
hp : tparavarsym;
+ paradef : tdef;
paraloc : pcgparalocation;
subreg : tsubregister;
pushaddr : boolean;
@@ -979,19 +953,21 @@ unit cpupara;
for i:=0 to paras.count-1 do
begin
hp:=tparavarsym(paras[i]);
- pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
+ paradef:=hp.vardef;
+ pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
if pushaddr then
begin
loc[1]:=X86_64_INTEGER_CLASS;
loc[2]:=X86_64_NO_CLASS;
paracgsize:=OS_ADDR;
paralen:=sizeof(pint);
+ paradef:=getpointerdef(paradef);
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);
+ getvalueparaloc(hp.varspez,paradef,loc[1],loc[2]);
+ paralen:=push_size(hp.varspez,paradef,p.proccalloption);
+ paracgsize:=def_cgsize(paradef);
{ integer sizes < 32 bit have to be sign/zero extended to 32 bit
on the caller side }
if (side=callerside) and
@@ -999,24 +975,27 @@ unit cpupara;
begin
paracgsize:=OS_S32;
paralen:=4;
+ paradef:=s32inttype;
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
+ (paradef.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
+ paracgsize:=OS_64;
+ paradef:=u64inttype;
end
else
begin
loc[1]:=X86_64_INTEGERSI_CLASS;
paracgsize:=OS_32;
+ paradef:=u32inttype;
end;
end;
@@ -1024,6 +1003,7 @@ unit cpupara;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].intsize:=paralen;
hp.paraloc[side].Alignment:=paraalign;
+ hp.paraloc[side].def:=paradef;
if paralen>0 then
begin
{ Enough registers free? }
diff --git a/mips/ide/fp.pas b/mips/ide/fp.pas
index 37a24b54bc..cedc47a803 100644
--- a/mips/ide/fp.pas
+++ b/mips/ide/fp.pas
@@ -177,8 +177,9 @@ begin
'C' : { custom config file (BP compatiblity) }
if BeforeINI then
begin
+ delete(param,1,1); // delete C
if (length(Param)>=1) and (Param[1] in['=',':']) then
- Delete(Param,1,1); { eat separator }
+ Delete(Param,1,1); { eat optional separator }
IniFileName:=Param;
end;
'R' : { enter the directory last exited from (BP comp.) }
diff --git a/mips/ide/fpredir.pas b/mips/ide/fpredir.pas
index a553911d33..66f8a569ba 100644
--- a/mips/ide/fpredir.pas
+++ b/mips/ide/fpredir.pas
@@ -79,6 +79,7 @@ const
Implementation
Uses
+ sysutils,
{$ifdef go32v2}
go32,
{$endif go32v2}
@@ -280,7 +281,8 @@ end;
function LocateExeFile(var FileName:string): boolean;
var
- dir,s,d,n,e : string;
+ S : AnsiString;
+ dir,d,n,e : string;
i : longint;
begin
LocateExeFile:=False;
@@ -299,7 +301,7 @@ begin
Exit;
end;
- S:=GetEnv('PATH');
+ S:=sysutils.GetEnvironmentVariable('PATH');
While Length(S)>0 do
begin
i:=1;
@@ -637,7 +639,8 @@ end;
function LocateExeFile(var FileName:string): boolean;
var
- dir,s,d,n,e : string;
+ S : AnsiString;
+ dir,d,n,e : string;
i : longint;
begin
LocateExeFile:=False;
@@ -656,7 +659,7 @@ begin
Exit;
end;
- S:=GetEnv('PATH');
+ S:=sysutils.GetEnvironmentVariable('PATH');
While Length(S)>0 do
begin
i:=1;
diff --git a/mips/ide/fputils.pas b/mips/ide/fputils.pas
index 1000e86570..25f89a2966 100644
--- a/mips/ide/fputils.pas
+++ b/mips/ide/fputils.pas
@@ -16,11 +16,13 @@ unit FPUtils;
interface
-uses Objects;
+uses
+ Sysutils,
+ Objects;
const
dirsep = System.DirectorySeparator;
-
+
{$ifdef Unix}
listsep = [';',':'];
exeext = '';
@@ -419,7 +421,8 @@ end;
function LocateExeFile(var FileName:string): boolean;
var
- dir,s : string;
+ dir : string;
+ s : ansistring;
i : longint;
begin
LocateExeFile:=False;
@@ -429,7 +432,7 @@ begin
Exit;
end;
- S:=GetEnv('PATH');
+ S:=sysutils.GetEnvironmentVariable('PATH');
While Length(S)>0 do
begin
i:=1;
diff --git a/mips/packages/fcl-db/src/base/bufdataset.pas b/mips/packages/fcl-db/src/base/bufdataset.pas
index 5d88dfcbd5..e271f51d03 100644
--- a/mips/packages/fcl-db/src/base/bufdataset.pas
+++ b/mips/packages/fcl-db/src/base/bufdataset.pas
@@ -353,7 +353,7 @@ type
constructor create(AStream : TStream); virtual;
// Load a dataset from stream:
// Load the field-definitions from a stream.
- procedure LoadFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
+ procedure LoadFieldDefs(AFieldDefs : TFieldDefs; var AnAutoIncValue : integer); virtual; abstract;
// Is called before the records are loaded
procedure InitLoadRecords; virtual; abstract;
// Return the RowState of the current record, and the order of the update
@@ -367,7 +367,7 @@ type
// Store a dataset to stream:
// Save the field-definitions to a stream.
- procedure StoreFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
+ procedure StoreFieldDefs(AFieldDefs : TFieldDefs; AnAutoIncValue : integer); virtual; abstract;
// Save a record from the current record-buffer to the stream
procedure StoreRecord(ADataset : TCustomBufDataset; ARowState : TRowState; AUpdOrder : integer = 0); virtual; abstract;
// Is called after all records are stored
@@ -381,8 +381,8 @@ type
TFpcBinaryDatapacketReader = class(TDataPacketReader)
public
- procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
- procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override;
+ procedure LoadFieldDefs(AFieldDefs : TFieldDefs; var AnAutoIncValue : integer); override;
+ procedure StoreFieldDefs(AFieldDefs : TFieldDefs; AnAutoIncValue : integer); override;
function GetRecordRowState(out AUpdOrder : Integer) : TRowState; override;
procedure FinalizeStoreRecords; override;
function GetCurrentRecord : boolean; override;
@@ -416,6 +416,8 @@ type
FOpen : Boolean;
FUpdateBuffer : TRecordsUpdateBuffer;
FCurrentUpdateBuffer : integer;
+ FAutoIncValue : longint;
+ FAutoIncField : TAutoIncField;
FIndexDefs : TIndexDefs;
@@ -457,7 +459,6 @@ type
procedure InitDefaultIndexes;
protected
procedure UpdateIndexDefs; override;
- function GetNewBlobBuffer : PBlobBuffer;
function GetNewWriteBlobBuffer : PBlobBuffer;
procedure FreeBlobBuffer(var ABlobBuffer: PBlobBuffer);
procedure SetRecNo(Value: Longint); override;
@@ -523,6 +524,7 @@ type
function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override;
procedure AddIndex(const AName, AFields : string; AOptions : TIndexOptions; const ADescFields: string = '';
const ACaseInsFields: string = ''); virtual;
+ function GetNewBlobBuffer : PBlobBuffer;
procedure SetDatasetPacket(AReader : TDataPacketReader);
procedure GetDatasetPacket(AWriter : TDataPacketReader);
@@ -765,6 +767,7 @@ begin
FIndexesCount:=0;
FIndexDefs := TIndexDefs.Create(Self);
+ FAutoIncValue:=-1;
SetLength(FUpdateBuffer,0);
SetLength(FBlobBuffers,0);
@@ -1120,6 +1123,7 @@ var IndexNr : integer;
i : integer;
begin
+ FAutoIncField:=nil;
if not Assigned(FDatasetReader) and (FileName<>'') then
begin
FFileStream := TFileStream.Create(FileName,fmOpenRead);
@@ -1132,14 +1136,22 @@ begin
// reading from a stream in some other way implemented by a descendent)
// If there are less fields then FieldDefs we know for sure that the dataset
// is not (correctly) created.
- if Fields.Count<FieldDefs.Count then
- DatabaseError(SErrNoDataset);
+
+ // commented for now. If there are constant expressions in the select
+ // statement they are ftunknown, and not created.
+ // See mantis #22030
+
+ // if Fields.Count<FieldDefs.Count then
+ // DatabaseError(SErrNoDataset);
+
// If there is a field with FieldNo=0 then the fields are not found to the
// FieldDefs which is a sign that there is no dataset created. (Calculated and
- // lookupfields have FielNo=-1)
+ // lookupfields have FieldNo=-1)
for i := 0 to Fields.Count-1 do
if fields[i].FieldNo=0 then
- DatabaseError(SErrNoDataset);
+ DatabaseError(SErrNoDataset)
+ else if (FAutoIncValue>-1) and (fields[i] is TAutoIncField) and not assigned(FAutoIncField) then
+ FAutoIncField := TAutoIncField(fields[i]);
InitDefaultIndexes;
CalcRecordSize;
@@ -1212,6 +1224,8 @@ begin
SetLength(FFieldBufPositions,0);
+ FAutoIncValue:=-1;
+
if assigned(FParser) then FreeAndNil(FParser);
FReadFromFile:=false;
end;
@@ -2189,6 +2203,8 @@ Var ABuff : TRecordBuffer;
i : integer;
blobbuf : tbufblobfield;
NullMask : pbyte;
+ li : longint;
+ StoreReadOnly: boolean;
ABookmark : PBufBookmark;
begin
@@ -2209,6 +2225,21 @@ begin
if State = dsInsert then
begin
+ if assigned(FAutoIncField) then
+ begin
+ li := FAutoIncValue;
+ // In principle all TAutoIncfields are read-only, but in theory it is
+ // possible to set readonly to false.
+ StoreReadOnly:=FAutoIncField.ReadOnly;
+ FAutoIncField.ReadOnly:=false;
+ try
+ FAutoIncField.SetData(@li);
+ finally
+ FAutoIncField.ReadOnly:=FAutoIncField.ReadOnly;
+ end;
+ inc(FAutoIncValue);
+ end;
+
// The active buffer is the newly created TDataset record,
// from which the bookmark is set to the record where the new record should be
// inserted
@@ -2650,7 +2681,7 @@ begin
try
//CheckActive;
ABookMark:=@ATBookmark;
- FDatasetReader.StoreFieldDefs(FieldDefs);
+ FDatasetReader.StoreFieldDefs(FieldDefs,FAutoIncValue);
StoreDSState:=SetTempState(dsFilter);
ScrollResult:=FCurrentIndex.ScrollFirst;
@@ -2727,26 +2758,31 @@ begin
end;
procedure TCustomBufDataset.CreateDataset;
+var AStoreFilename: string;
+
begin
CheckInactive;
- if not ((FieldCount=0) or (FieldDefs.Count=0)) then
+ if ((FieldCount=0) or (FieldDefs.Count=0)) then
begin
- Open;
- Exit;
+ if (FieldDefs.Count>0) then
+ CreateFields
+ else if (fields.Count>0) then
+ begin
+ InitFieldDefsFromfields;
+ BindFields(True);
+ end
+ else
+ raise Exception.Create(SErrNoFieldsDefined);
+ FAutoIncValue:=1;
end;
- if (FieldDefs.Count>0) then
- begin
- CreateFields;
- Open;
- end
- else if (fields.Count>0) then
- begin
- InitFieldDefsFromfields;
- BindFields(True);
+ // When a filename is set, do not read from this file
+ AStoreFilename:=FFileName;
+ FFileName := '';
+ try
Open;
- end
- else
- raise Exception.Create(SErrNoFieldsDefined);
+ finally
+ FFileName:=AStoreFilename;
+ end;
end;
function TCustomBufDataset.BookmarkValid(ABookmark: TBookmark): Boolean;
@@ -2766,8 +2802,12 @@ end;
procedure TCustomBufDataset.IntLoadFielddefsFromFile;
begin
- FDatasetReader.LoadFielddefs(FieldDefs);
- if DefaultFields then CreateFields;
+ FieldDefs.Clear;
+ FDatasetReader.LoadFielddefs(FieldDefs, FAutoIncValue);
+ if DefaultFields then
+ CreateFields
+ else
+ BindFields(true);
end;
procedure TCustomBufDataset.IntLoadRecordsFromFile;
@@ -3404,7 +3444,7 @@ end;
const FpcBinaryIdent = 'BinBufDataset';
-procedure TFpcBinaryDatapacketReader.LoadFieldDefs(AFieldDefs: TFieldDefs);
+procedure TFpcBinaryDatapacketReader.LoadFieldDefs(AFieldDefs: TFieldDefs; var AnAutoIncValue: integer);
var FldCount : word;
i : integer;
@@ -3425,9 +3465,11 @@ begin
if Stream.ReadByte = 1 then
Attributes := Attributes + [faReadonly];
end;
+ Stream.ReadBuffer(i,sizeof(i));
+ AnAutoIncValue := i;
end;
-procedure TFpcBinaryDatapacketReader.StoreFieldDefs(AFieldDefs: TFieldDefs);
+procedure TFpcBinaryDatapacketReader.StoreFieldDefs(AFieldDefs: TFieldDefs; AnAutoIncValue: integer);
var i : integer;
begin
Stream.Write(FpcBinaryIdent[1],length(FpcBinaryIdent));
@@ -3445,6 +3487,8 @@ begin
else
Stream.WriteByte(0);
end;
+ i := AnAutoIncValue;
+ Stream.WriteBuffer(i,sizeof(i));
end;
function TFpcBinaryDatapacketReader.GetRecordRowState(out AUpdOrder : Integer) : TRowState;
diff --git a/mips/packages/fcl-db/src/base/dataset.inc b/mips/packages/fcl-db/src/base/dataset.inc
index a454711166..427c84f319 100644
--- a/mips/packages/fcl-db/src/base/dataset.inc
+++ b/mips/packages/fcl-db/src/base/dataset.inc
@@ -85,14 +85,8 @@ Procedure TDataset.BindFields(Binding: Boolean);
var i, FieldIndex: Integer;
FieldDef: TFieldDef;
begin
- {
- Here some magic will be needed later; for now just simply set
- Just set fieldno from listindex...
- Later we should take it from the fielddefs.
- // ATM Set by CreateField ...
- For I:=0 to FFieldList.Count-1 do
- FFieldList[i].FFieldNo:=I;
- }
+ { FieldNo is set to -1 for calculated/lookup fields, to 0 for unbound field
+ and for bound fields it is set to FieldDef.FieldNo }
FCalcFieldsSize := 0;
FBlobFieldCount := 0;
for i := 0 to Fields.Count - 1 do
@@ -124,7 +118,7 @@ begin
FOffset := FBlobFieldCount;
Inc(FBlobFieldCount);
end;
- end else FFieldNo := FieldIndex;
+ end else FFieldNo := 0;
end;
end else FFieldNo := 0;
end;
@@ -910,15 +904,16 @@ begin
FieldDefs.BeginUpdate;
try
for i := 0 to Fields.Count-1 do with fields[i] do
- begin
- with TFieldDef.Create(FieldDefs,FieldName,DataType,Size,Required,i+1) do
+ if not (FieldKind in [fkCalculated,fkLookup]) then // Do not add fielddefs for calculated/lookup fields.
begin
- if Required then Attributes := attributes + [faRequired];
- if ReadOnly then Attributes := attributes + [faReadOnly];
- if DataType = ftBCD then precision := (fields[i] as TBCDField).Precision
- else if DataType = ftFMTBcd then precision := (fields[i] as TFMTBCDField).Precision;
+ with TFieldDef.Create(FieldDefs,FieldName,DataType,Size,Required,FieldDefs.Count+1) do
+ begin
+ if Required then Attributes := attributes + [faRequired];
+ if ReadOnly then Attributes := attributes + [faReadOnly];
+ if DataType = ftBCD then precision := (fields[i] as TBCDField).Precision
+ else if DataType = ftFMTBcd then precision := (fields[i] as TFMTBCDField).Precision;
+ end;
end;
- end;
finally
FieldDefs.EndUpdate;
end;
@@ -1822,33 +1817,20 @@ end;
Procedure TDataset.GetFieldList(List: TList; const FieldNames: string);
- Function NextName(Var S : String) : String;
-
- Var
- P : integer;
-
- begin
- P:=Pos(';',S);
- If (P=0) then
- P:=Length(S)+1;
- Result:=Copy(S,1,P-1);
- system.Delete(S,1,P);
- end;
-
var
F: TField;
- Names,N : String;
+ N: String;
+ StrPos: Integer;
begin
- Names:=FieldNames;
- N:=Nextname(Names);
- while (N<>'') do
- begin
- F:=FieldByName(N);
- If Assigned(List) then
- List.Add(F);
- N:=NextName(Names);
- end;
+ if (FieldNames = '') or (List = nil) then
+ Exit;
+ StrPos := 1;
+ repeat
+ N := ExtractFieldName(FieldNames, StrPos);
+ F := FieldByName(N);
+ List.Add(F);
+ until StrPos > Length(FieldNames);
end;
Procedure TDataset.GetFieldNames(List: TStrings);
diff --git a/mips/packages/fcl-db/src/base/dbconst.pas b/mips/packages/fcl-db/src/base/dbconst.pas
index 0ffdb406dc..f8f4a27817 100644
--- a/mips/packages/fcl-db/src/base/dbconst.pas
+++ b/mips/packages/fcl-db/src/base/dbconst.pas
@@ -111,7 +111,7 @@ Resourcestring
SRollBackRetaining = 'Rollback and retaining transaction';
SErrNoFieldsDefined = 'Can not create a dataset when there are no fielddefinitions or fields defined';
SErrApplyUpdBeforeRefresh= 'Must apply updates before refreshing data';
- SErrNoDataset = 'Missing underlying dataset, can not open';
+ SErrNoDataset = 'Missing (compatible) underlying dataset, can not open';
Implementation
diff --git a/mips/packages/fcl-db/src/base/dsparams.inc b/mips/packages/fcl-db/src/base/dsparams.inc
index 601dabb6f7..72d16d0771 100644
--- a/mips/packages/fcl-db/src/base/dsparams.inc
+++ b/mips/packages/fcl-db/src/base/dsparams.inc
@@ -125,27 +125,20 @@ end;
Procedure TParams.GetParamList(List: TList; const ParamNames: string);
- Function NextName(Var S : String) : String;
- Var
- P : Integer;
- begin
- P:=Pos(';',S);
- If (P=0) then
- P:=Length(S)+1;
- Result:=Copy(S,1,P-1);
- system.Delete(S,1,P);
- end;
-
Var
- L,N : String;
+ P: TParam;
+ N: String;
+ StrPos: Integer;
begin
- L:=ParamNames;
- While (Length(L)>0) do
- begin
- N:=NextName(L);
- List.Add(ParamByName(N));
- end;
+ if (ParamNames = '') or (List = nil) then
+ Exit;
+ StrPos := 1;
+ repeat
+ N := ExtractFieldName(ParamNames, StrPos);
+ P := ParamByName(N);
+ List.Add(P);
+ until StrPos > Length(ParamNames);
end;
Function TParams.IsEqual(Value: TParams): Boolean;
@@ -220,7 +213,8 @@ begin
repeat // skip until at end of line
Inc(p);
until p^ in [#10, #0];
- end
+ end;
+ if p^<>#0 then Inc(p); // newline is part of comment
end;
'/': // possible start of /* */ comment
begin
diff --git a/mips/packages/fcl-db/src/base/xmldatapacketreader.pp b/mips/packages/fcl-db/src/base/xmldatapacketreader.pp
index 94ea8b7c13..ce443f59e0 100644
--- a/mips/packages/fcl-db/src/base/xmldatapacketreader.pp
+++ b/mips/packages/fcl-db/src/base/xmldatapacketreader.pp
@@ -48,10 +48,10 @@ type
FLastChange : integer;
public
destructor destroy; override;
- procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override;
+ procedure StoreFieldDefs(AFieldDefs : TFieldDefs; AnAutoIncValue : integer); override;
procedure StoreRecord(ADataset : TCustomBufDataset; ARowState : TRowState; AUpdOrder : integer = 0); override;
procedure FinalizeStoreRecords; override;
- procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
+ procedure LoadFieldDefs(AFieldDefs : TFieldDefs; var AnAutoIncValue : integer); override;
procedure InitLoadRecords; override;
function GetCurrentRecord : boolean; override;
function GetRecordRowState(out AUpdOrder : Integer) : TRowState; override;
@@ -62,7 +62,7 @@ type
implementation
-uses xmlwrite, xmlread;
+uses xmlwrite, xmlread, base64;
const
XMLFieldtypenames : Array [TFieldType] of String[15] =
@@ -74,21 +74,21 @@ const
'i4',
'boolean',
'r8',
- 'r8',
+ 'r8:Money',
'fixed',
'date',
'time',
'datetime',
'bin.hex',
'bin.hex',
- 'i4',
- 'bin.hex',
- 'bin.hex',
- 'bin.hex',
- 'bin.hex',
- 'bin.hex',
- 'bin.hex',
- 'bin.hex',
+ 'i4:Autoinc',
+ 'bin.hex:Binary',
+ 'bin.hex:Text',
+ 'bin.hex:Graphics',
+ 'bin.hex:Formatted',
+ 'bin.hex:Ole',
+ 'bin.hex:Ole',
+ 'bin.hex:Graphics',
'',
'string',
'string',
@@ -104,7 +104,7 @@ const
'',
'',
'',
- '',
+ 'fixedFMT',
'',
''
);
@@ -123,7 +123,7 @@ begin
inherited destroy;
end;
-procedure TXMLDatapacketReader.LoadFieldDefs(AFieldDefs : TFieldDefs);
+procedure TXMLDatapacketReader.LoadFieldDefs(AFieldDefs: TFieldDefs; var AnAutoIncValue: integer);
function GetNodeAttribute(const aNode : TDOMNode; AttName : String) : string;
var AnAttr : TDomNode;
@@ -137,7 +137,9 @@ var i : integer;
AFieldDef : TFieldDef;
iFieldType : TFieldType;
FTString : string;
+ SubFTString : string;
AFieldNode : TDOMNode;
+ AnAutoIncNode: TDomNode;
begin
ReadXMLFile(XMLDocument,Stream);
@@ -160,6 +162,9 @@ begin
AFieldDef.Name:=GetNodeAttribute(AFieldNode,'attrname');
AFieldDef.Size:=StrToIntDef(GetNodeAttribute(AFieldNode,'width'),0);
FTString:=GetNodeAttribute(AFieldNode,'fieldtype');
+ SubFTString:=GetNodeAttribute(AFieldNode,'subtype');
+ if SubFTString<>'' then
+ FTString:=FTString+':'+SubFTString;
AFieldDef.DataType:=ftUnknown;
for iFieldType:=low(TFieldType) to high(TFieldType) do
@@ -171,18 +176,24 @@ begin
end;
end;
- FChangeLogNode := MetaDataNode.FindNode('PARAMS');
- if assigned(FChangeLogNode) then
- FChangeLogNode := FChangeLogNode.Attributes.GetNamedItem('CHANGE_LOG');
+ FParamsNode := MetaDataNode.FindNode('PARAMS');
+ if assigned(FParamsNode) then
+ begin
+ FChangeLogNode := FParamsNode.Attributes.GetNamedItem('CHANGE_LOG');
+ AnAutoIncNode := FParamsNode.Attributes.GetNamedItem('AUTOINCVALUE');
+ if assigned(AnAutoIncNode) then
+ AnAutoIncValue := StrToIntDef(AnAutoIncNode.NodeValue,-1);
+ end;
FRowDataNode := DataPacketNode.FindNode('ROWDATA');
FRecordNode := nil;
end;
-procedure TXMLDatapacketReader.StoreFieldDefs(AFieldDefs: TFieldDefs);
+procedure TXMLDatapacketReader.StoreFieldDefs(AFieldDefs: TFieldDefs; AnAutoIncValue: integer);
-var i : integer;
+var i,p : integer;
AFieldNode : TDOMElement;
+ AStringFT : string;
begin
XMLDocument := TXMLDocument.Create;
@@ -198,22 +209,15 @@ begin
if Name <> '' then AFieldNode.SetAttribute('fieldname',Name);
AFieldNode.SetAttribute('attrname',DisplayName);
if size <> 0 then AFieldNode.SetAttribute('width',IntToStr(Size));
- AFieldNode.SetAttribute('fieldtype',XMLFieldtypenames[DataType]);
- case DataType of
- ftAutoInc : begin
- AFieldNode.SetAttribute('readonly','true');
- AFieldNode.SetAttribute('subtype','Autoinc');
- end;
- ftCurrency: AFieldNode.SetAttribute('subtype','Money');
- ftVarBytes,
- ftBlob : AFieldNode.SetAttribute('subtype','Binary');
- ftMemo : AFieldNode.SetAttribute('subtype','Text');
- ftTypedBinary,
- ftGraphic: AFieldNode.SetAttribute('subtype','Graphics');
- ftFmtMemo : AFieldNode.SetAttribute('subtype','Formatted');
- ftParadoxOle,
- ftDBaseOle : AFieldNode.SetAttribute('subtype','Ole');
- end; {case}
+ AStringFT:=XMLFieldtypenames[DataType];
+ p := pos(':',AStringFT);
+ if p > 1 then
+ begin
+ AFieldNode.SetAttribute('fieldtype',copy(AStringFT,1,p-1));
+ AFieldNode.SetAttribute('subtype',copy(AStringFT,p+1,25));
+ end
+ else
+ AFieldNode.SetAttribute('fieldtype',AStringFT);
if faReadonly in Attributes then AFieldNode.SetAttribute('readonly','true');
FieldsNode.AppendChild(AFieldNode);
@@ -221,6 +225,9 @@ begin
MetaDataNode.AppendChild(FieldsNode);
FParamsNode := XMLDocument.CreateElement('PARAMS');
+ if AnAutoIncValue>-1 then
+ (FParamsNode as TDomElement).SetAttribute('AUTOINCVALUE',IntToStr(AnAutoIncValue));
+
MetaDataNode.AppendChild(FParamsNode);
DataPacketNode.AppendChild(MetaDataNode);
FRowDataNode := XMLDocument.CreateElement('ROWDATA');
@@ -329,28 +336,49 @@ begin
end;
procedure TXMLDatapacketReader.RestoreRecord(ADataset : TCustomBufDataset);
-var FieldNr : integer;
- AFieldNode : TDomNode;
+var FieldNr : integer;
+ AFieldNode : TDomNode;
+ ABufBlobField: TBufBlobField;
+ AField: TField;
+ s: string;
begin
- with ADataset do for FieldNr:=0 to FieldCount-1 do
+ with ADataset do for FieldNr:=0 to FieldDefs.Count-1 do
begin
- AFieldNode := FRecordNode.Attributes.GetNamedItem(Fields[FieldNr].FieldName);
+ AFieldNode := FRecordNode.Attributes.GetNamedItem(FieldDefs[FieldNr].Name);
if assigned(AFieldNode) then
begin
- Fields[FieldNr].AsString := AFieldNode.NodeValue; // set it to the filterbuffer
+ if FieldDefs[FieldNr].DataType in [ftMemo,ftBlob] then
+ begin
+ ABufBlobField.BlobBuffer:=ADataset.GetNewBlobBuffer;
+ afield := Fields.FieldByNumber(FieldDefs[FieldNr].FieldNo);
+ AField.SetData(@ABufBlobField);
+ s := AFieldNode.NodeValue;
+ if (FieldDefs[FieldNr].DataType = ftBlob) and (s<>'') then
+ s := DecodeStringBase64(s);
+ ABufBlobField.BlobBuffer^.Size:=length(s);
+ ReAllocMem(ABufBlobField.BlobBuffer^.Buffer,ABufBlobField.BlobBuffer^.Size);
+ move(s[1],ABufBlobField.BlobBuffer^.Buffer^,ABufBlobField.BlobBuffer^.Size);
+ end
+ else
+ Fields.FieldByNumber(FieldDefs[FieldNr].FieldNo).AsString := AFieldNode.NodeValue; // set it to the filterbuffer
end
end;
end;
procedure TXMLDatapacketReader.StoreRecord(ADataset : TCustomBufDataset; ARowState : TRowState; AUpdOrder : integer = 0);
var FieldNr : Integer;
+ AField: TField;
ARecordNode : TDOMElement;
begin
inc(FEntryNr);
ARecordNode := XMLDocument.CreateElement('ROW');
- for FieldNr := 0 to ADataset.Fields.Count-1 do
+ for FieldNr := 0 to ADataset.FieldDefs.Count-1 do
begin
- ARecordNode.SetAttribute(ADataset.fields[FieldNr].FieldName,ADataset.fields[FieldNr].AsString);
+ AField := ADataset.Fields.FieldByNumber(ADataset.FieldDefs[FieldNr].FieldNo);
+ if AField.DataType=ftBlob then
+ ARecordNode.SetAttribute(AField.FieldName,EncodeStringBase64(AField.AsString))
+ else
+ ARecordNode.SetAttribute(AField.FieldName,AField.AsString);
end;
if ARowState<>[] then
begin
diff --git a/mips/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc b/mips/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
index 69485ee07a..9dd7f53784 100644
--- a/mips/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
+++ b/mips/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
@@ -530,9 +530,9 @@ begin
C:=Cursor as TCursorName;
if c.FStatementType in [stSelect,stExecProcedure] then
c.FNeedData:=False;
- If (C.FRes<>Nil) then
+ if assigned(C.FRes) then
begin
- Mysql_free_result(C.FRes);
+ mysql_free_result(C.FRes);
C.FRes:=Nil;
end;
SetLength(c.MapDSRowToMSQLRow,0);
@@ -588,16 +588,15 @@ var ASize, ADecimals: integer;
begin
Result := True;
ASize := AField^.length;
+ NewSize := 0;
case AField^.ftype of
FIELD_TYPE_LONGLONG:
begin
NewType := ftLargeint;
- NewSize := 0;
end;
FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_YEAR:
begin
NewType := ftSmallint;
- NewSize := 0;
end;
FIELD_TYPE_LONG, FIELD_TYPE_INT24:
begin
@@ -605,7 +604,6 @@ begin
NewType := ftAutoInc
else
NewType := ftInteger;
- NewSize := 0;
end;
{$ifdef mysql50_up}
FIELD_TYPE_NEWDECIMAL,
@@ -624,32 +622,25 @@ begin
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
begin
NewType := ftFloat;
- NewSize := 0;
end;
FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
begin
NewType := ftDateTime;
- NewSize := 0;
end;
FIELD_TYPE_DATE:
begin
NewType := ftDate;
- NewSize := 0;
end;
FIELD_TYPE_TIME:
begin
NewType := ftTime;
- NewSize := 0;
end;
FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
begin
// Since mysql server version 5.0.3 string-fields with a length of more
// then 256 characters are suported
if ASize>dsMaxStringSize then
- begin
- NewType := ftMemo;
- NewSize := 0;
- end
+ NewType := ftMemo
else
begin
if AField^.ftype = FIELD_TYPE_STRING then
@@ -676,8 +667,11 @@ begin
{$ELSE}
NewType := ftBlob;
{$ENDIF}
- NewSize := 0;
- end
+ end;
+{$IFDEF MYSQL50_UP}
+ FIELD_TYPE_BIT:
+ NewType := ftLargeInt;
+{$ENDIF}
else
Result := False;
end;
@@ -1028,6 +1022,15 @@ begin
end;
FIELD_TYPE_BLOB:
CreateBlob := True;
+{$IFDEF MYSQL50_UP}
+ FIELD_TYPE_BIT:
+ begin
+ VL := 0;
+ for VI := 0 to Len-1 do
+ VL := VL * 256 + PByte(Source+VI)^;
+ move(VL, Dest^, sizeof(LargeInt));
+ end;
+{$ENDIF}
end;
Result := True;
end;
diff --git a/mips/packages/fcl-db/src/sqldb/postgres/pqconnection.pp b/mips/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
index c335d2457f..c68693921c 100644
--- a/mips/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
+++ b/mips/packages/fcl-db/src/sqldb/postgres/pqconnection.pp
@@ -39,6 +39,7 @@ type
FConnectString : string;
FSQLDatabaseHandle : pointer;
FIntegerDateTimes : boolean;
+ procedure CheckResultError(res: PPGresult; conn:PPGconn; ErrMsg: string);
function TranslateFldType(res : PPGresult; Tuple : integer; out Size : integer) : TFieldType;
procedure ExecuteDirectPG(const Query : String);
protected
@@ -86,6 +87,15 @@ type
Class Function Description : String; override;
end;
+ EPQDatabaseError = class(EDatabaseError)
+ public
+ SEVERITY:string;
+ SQLSTATE: string;
+ MESSAGE_PRIMARY:string;
+ MESSAGE_DETAIL:string;
+ MESSAGE_HINT:string;
+ STATEMENT_POSITION:string;
+ end;
implementation
@@ -179,18 +189,10 @@ begin
res := PQexec(ASQLDatabaseHandle,pchar(query));
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- msg := PQerrorMessage(ASQLDatabaseHandle);
- PQclear(res);
- PQFinish(ASQLDatabaseHandle);
- DatabaseError(SDBCreateDropFailed + ' (PostgreSQL: ' + Msg + ')',self);
- end
- else
- begin
- PQclear(res);
- PQFinish(ASQLDatabaseHandle);
- end;
+ CheckResultError(res,ASQLDatabaseHandle,SDBCreateDropFailed);
+
+ PQclear(res);
+ PQFinish(ASQLDatabaseHandle);
{$IfDef LinkDynamically}
ReleasePostgres3;
{$EndIf}
@@ -212,18 +214,12 @@ begin
tr := trans as TPQTrans;
res := PQexec(tr.PGConn, 'ROLLBACK');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- PQclear(res);
- result := false;
- DatabaseError(SErrRollbackFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
- end
- else
- begin
- PQclear(res);
- PQFinish(tr.PGConn);
- result := true;
- end;
+
+ CheckResultError(res,tr.PGConn,SErrRollbackFailed);
+
+ PQclear(res);
+ PQFinish(tr.PGConn);
+ result := true;
end;
function TPQConnection.Commit(trans : TSQLHandle) : boolean;
@@ -236,18 +232,11 @@ begin
tr := trans as TPQTrans;
res := PQexec(tr.PGConn, 'COMMIT');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- PQclear(res);
- result := false;
- DatabaseError(SErrCommitFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
- end
- else
- begin
- PQclear(res);
- PQFinish(tr.PGConn);
- result := true;
- end;
+ CheckResultError(res,tr.PGConn,SErrCommitFailed);
+
+ PQclear(res);
+ PQFinish(tr.PGConn);
+ result := true;
end;
function TPQConnection.StartdbTransaction(trans : TSQLHandle; AParams : string) : boolean;
@@ -272,19 +261,10 @@ begin
begin
tr.ErrorOccured := False;
res := PQexec(tr.PGConn, 'BEGIN');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- result := false;
- PQclear(res);
- msg := PQerrorMessage(tr.PGConn);
- PQFinish(tr.PGConn);
- DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self);
- end
- else
- begin
- PQclear(res);
- result := true;
- end;
+ CheckResultError(res,tr.PGConn,sErrTransactionFailed);
+
+ PQclear(res);
+ result := true;
end;
end;
@@ -296,25 +276,13 @@ var
begin
tr := trans as TPQTrans;
res := PQexec(tr.PGConn, 'ROLLBACK');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- PQclear(res);
- DatabaseError(SErrRollbackFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
- end
- else
- begin
- PQclear(res);
- res := PQexec(tr.PGConn, 'BEGIN');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- PQclear(res);
- msg := PQerrorMessage(tr.PGConn);
- PQFinish(tr.PGConn);
- DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self);
- end
- else
- PQclear(res);
- end;
+ CheckResultError(res,tr.PGConn,SErrRollbackFailed);
+
+ PQclear(res);
+ res := PQexec(tr.PGConn, 'BEGIN');
+ CheckResultError(res,tr.PGConn,sErrTransactionFailed);
+
+ PQclear(res);
end;
procedure TPQConnection.CommitRetaining(trans : TSQLHandle);
@@ -325,25 +293,13 @@ var
begin
tr := trans as TPQTrans;
res := PQexec(tr.PGConn, 'COMMIT');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- PQclear(res);
- DatabaseError(SErrCommitFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self);
- end
- else
- begin
- PQclear(res);
- res := PQexec(tr.PGConn, 'BEGIN');
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- PQclear(res);
- msg := PQerrorMessage(tr.PGConn);
- PQFinish(tr.PGConn);
- DatabaseError(sErrTransactionFailed + ' (PostgreSQL: ' + msg + ')',self);
- end
- else
- PQclear(res);
- end;
+ CheckResultError(res,tr.PGConn,SErrCommitFailed);
+
+ PQclear(res);
+ res := PQexec(tr.PGConn, 'BEGIN');
+ CheckResultError(res,tr.PGConn,sErrTransactionFailed);
+
+ PQclear(res);
end;
@@ -387,6 +343,50 @@ begin
end;
+procedure TPQConnection.CheckResultError(res: PPGresult; conn: PPGconn;
+ ErrMsg: string);
+var
+ serr:string;
+ E: EPQDatabaseError;
+ CompName: string;
+ SEVERITY:string;
+ SQLSTATE: string;
+ MESSAGE_PRIMARY:string;
+ MESSAGE_DETAIL:string;
+ MESSAGE_HINT:string;
+ STATEMENT_POSITION:string;
+
+begin
+ if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
+ begin
+ SEVERITY:=PQresultErrorField(res,ord('S'));
+ SQLSTATE:=PQresultErrorField(res,ord('C'));
+ MESSAGE_PRIMARY:=PQresultErrorField(res,ord('M'));
+ MESSAGE_DETAIL:=PQresultErrorField(res,ord('D'));
+ MESSAGE_HINT:=PQresultErrorField(res,ord('H'));
+ STATEMENT_POSITION:=PQresultErrorField(res,ord('P'));
+ serr:=PQresultErrorMessage(res)+LineEnding+
+ 'Severity: '+ SEVERITY +LineEnding+
+ 'SQL State: '+ SQLSTATE +LineEnding+
+ 'Primary Error: '+ MESSAGE_PRIMARY +LineEnding+
+ 'Error Detail: '+ MESSAGE_DETAIL +LineEnding+
+ 'Hint: '+ MESSAGE_HINT +LineEnding+
+ 'Character: '+ STATEMENT_POSITION +LineEnding;
+ pqclear(res);
+ if assigned(conn) then
+ PQFinish(conn);
+ if Self.Name = '' then CompName := Self.ClassName else CompName := Self.Name;
+ E:=EPQDatabaseError.CreateFmt('%s : %s (PostgreSQL: %s)', [CompName,ErrMsg, serr]);
+ E.SEVERITY:=SEVERITY;
+ E.SQLSTATE:=SQLSTATE;
+ E.MESSAGE_PRIMARY:=MESSAGE_PRIMARY;
+ E.MESSAGE_DETAIL:=MESSAGE_DETAIL;
+ E.MESSAGE_HINT:=MESSAGE_HINT;
+ E.STATEMENT_POSITION:=STATEMENT_POSITION;
+ raise E;
+ end;
+end;
+
function TPQConnection.TranslateFldType(res : PPGresult; Tuple : integer; out Size : integer) : TFieldType;
const VARHDRSZ=sizeof(longint);
var li : longint;
@@ -525,7 +525,7 @@ const TypeStrings : array[TFieldType] of string =
);
-var s : string;
+var s,serr : string;
i : integer;
begin
@@ -559,11 +559,7 @@ begin
end;
s := s + ' as ' + buf;
res := pqexec(tr.PGConn,pchar(s));
- if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
- begin
- pqclear(res);
- DatabaseError(SErrPrepareFailed + ' (PostgreSQL: ' + PQerrorMessage(tr.PGConn) + ')',self)
- end;
+ CheckResultError(res,nil,SErrPrepareFailed);
// if statement is INSERT, UPDATE, DELETE with RETURNING clause, then
// override the statement type derrived by parsing the query.
if (FStatementType in [stInsert,stUpdate,stDelete]) and (pos('RETURNING', upcase(s)) > 0) then
diff --git a/mips/packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp b/mips/packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp
index f463a3cfa4..fdec42a959 100644
--- a/mips/packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp
+++ b/mips/packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp
@@ -122,7 +122,6 @@ end;
procedure TPQEventMonitor.SetRegistered(AValue: Boolean);
begin
- FRegistered := AValue;
if not (csDesigning in ComponentState) then
if AValue then
RegisterEvents
diff --git a/mips/packages/fcl-db/src/sqldb/sqldb.pp b/mips/packages/fcl-db/src/sqldb/sqldb.pp
index 97e2f1ee97..9a4ea37b22 100644
--- a/mips/packages/fcl-db/src/sqldb/sqldb.pp
+++ b/mips/packages/fcl-db/src/sqldb/sqldb.pp
@@ -1010,7 +1010,7 @@ begin
end;
if FWhereStartPos = 0 then
- SQLstr := SQLstr + ' where (' + Filter + ')'
+ SQLstr := SQLstr + ' where (' + ServerFilter + ')'
else if FWhereStopPos > 0 then
system.insert(' and ('+ServerFilter+') ',SQLstr,FWhereStopPos+2)
else
@@ -1217,18 +1217,17 @@ end;
function TCustomSQLQuery.SQLParser(const ASQL : string) : TStatementType;
-type TParsePart = (ppStart,ppWith,ppSelect,ppFrom,ppWhere,ppGroup,ppOrder,ppComment,ppBogus);
+type TParsePart = (ppStart,ppWith,ppSelect,ppTableName,ppFrom,ppWhere,ppGroup,ppOrder,ppBogus);
+ TPhraseSeparator = (sepNone, sepWhiteSpace, sepComma, sepComment, sepParentheses, sepEnd);
Var
- PSQL,CurrentP,
+ PSQL, CurrentP, SavedP,
PhraseP, PStatementPart : pchar;
S : string;
ParsePart : TParsePart;
- StrLength : Integer;
- EndOfComment : Boolean;
BracketCount : Integer;
ConnOptions : TConnOptions;
- FFromPart : String;
+ Separator : TPhraseSeparator;
begin
PSQL:=Pchar(ASQL);
@@ -1237,42 +1236,57 @@ begin
CurrentP := PSQL-1;
PhraseP := PSQL;
+ FTableName := '';
+ FUpdateable := False;
+
FWhereStartPos := 0;
FWhereStopPos := 0;
ConnOptions := TSQLConnection(DataBase).ConnOptions;
- FUpdateable := False;
repeat
begin
inc(CurrentP);
-
- EndOfComment := SkipComments(CurrentP, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions);
- if EndOfcomment then dec(CurrentP);
- if EndOfComment and (ParsePart = ppStart) then PhraseP := CurrentP;
-
- // skip everything between bracket, since it could be a sub-select, and
- // further nothing between brackets could be interesting for the parser.
- if CurrentP^='(' then
- begin
- inc(currentp);
- BracketCount := 0;
- while (currentp^ <> #0) and ((currentp^ <> ')') or (BracketCount > 0 )) do
+ SavedP := CurrentP;
+
+ case CurrentP^ of
+ ' ', #9, #10, #11, #12, #13:
+ Separator := sepWhiteSpace;
+ ',':
+ Separator := sepComma;
+ #0, ';':
+ Separator := sepEnd;
+ '(':
begin
- if currentp^ = '(' then inc(bracketcount)
- else if currentp^ = ')' then dec(bracketcount);
- inc(currentp);
+ Separator := sepParentheses;
+ // skip everything between brackets, since it could be a sub-select, and
+ // further nothing between brackets could be interesting for the parser.
+ BracketCount := 1;
+ repeat
+ inc(CurrentP);
+ if CurrentP^ = '(' then inc(BracketCount)
+ else if CurrentP^ = ')' then dec(BracketCount);
+ until (CurrentP^ = #0) or (BracketCount = 0);
+ if CurrentP^ <> #0 then inc(CurrentP);
end;
- EndOfComment := True;
- end;
+ else
+ if SkipComments(CurrentP, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions) then
+ Separator := sepComment
+ else
+ Separator := sepNone;
+ end;
+
+ if (CurrentP > SavedP) and (SavedP > PhraseP) then
+ CurrentP := SavedP; // there is something before comment or left parenthesis
- if EndOfComment or (CurrentP^ in [' ',#13,#10,#9,#0,';']) then
+ if Separator <> sepNone then
begin
- if (CurrentP-PhraseP > 0) or (CurrentP^ in [';',#0]) then
+ if ((Separator in [sepWhitespace,sepComment]) and (PhraseP = SavedP)) then
+ PhraseP := CurrentP; // skip comments(but not parentheses) and white spaces
+
+ if (CurrentP-PhraseP > 0) or (Separator = sepEnd) then
begin
- strLength := CurrentP-PhraseP;
- Setlength(S,strLength);
- if strLength > 0 then Move(PhraseP^,S[1],(strLength));
+ SetString(s, PhraseP, CurrentP-PhraseP);
s := uppercase(s);
case ParsePart of
@@ -1284,7 +1298,6 @@ begin
else break;
end;
if not FParseSQL then break;
- PStatementPart := CurrentP;
end;
ppWith : begin
// WITH [RECURSIVE] CTE_name [ ( column_names ) ] AS ( CTE_query_definition ) [, ...]
@@ -1299,69 +1312,53 @@ begin
end;
ppSelect : begin
if s = 'FROM' then
+ ParsePart := ppTableName;
+ end;
+ ppTableName:
+ begin
+ // Meta-data requests are never updateable
+ // and select-statements from more then one table
+ // and/or derived tables are also not updateable
+ if (FSchemaType = stNoSchema) and
+ (Separator in [sepWhitespace, sepComment, sepEnd]) then
begin
- ParsePart := ppFrom;
- PhraseP := CurrentP;
- PStatementPart := CurrentP;
+ FTableName := s;
+ FUpdateable := True;
end;
+ ParsePart := ppFrom;
end;
ppFrom : begin
- if (s = 'WHERE') or (s = 'ORDER') or (s = 'GROUP') or (s = 'LIMIT') or (CurrentP^=#0) or (CurrentP^=';') then
+ if (s = 'WHERE') or (s = 'GROUP') or (s = 'ORDER') or (s = 'LIMIT') or (s = 'ROWS') or
+ (Separator = sepEnd) then
begin
- if (s = 'WHERE') then
- begin
- ParsePart := ppWhere;
- StrLength := PhraseP-PStatementPart;
- end
- else if (s = 'GROUP') then
- begin
- ParsePart := ppGroup;
- StrLength := PhraseP-PStatementPart;
- end
- else if (s = 'ORDER') then
- begin
- ParsePart := ppOrder;
- StrLength := PhraseP-PStatementPart
- end
- else if (s = 'LIMIT') then
- begin
- ParsePart := ppBogus;
- StrLength := PhraseP-PStatementPart
- end
- else
- begin
- ParsePart := ppBogus;
- StrLength := CurrentP-PStatementPart;
- end;
- if Result = stSelect then
- begin
- Setlength(FFromPart,StrLength);
- Move(PStatementPart^,FFromPart[1],(StrLength));
- FFromPart := trim(FFromPart);
-
- // Meta-data requests and are never updateable select-statements
- // from more then one table are not updateable
- if (FSchemaType=stNoSchema) and
- (ExtractStrings([',',' '],[],pchar(FFromPart),nil) = 1) then
- begin
- FUpdateable := True;
- FTableName := FFromPart;
- end;
- end;
-
- FWhereStartPos := PStatementPart-PSQL+StrLength+1;
+ case s of
+ 'WHERE': ParsePart := ppWhere;
+ 'GROUP': ParsePart := ppGroup;
+ 'ORDER': ParsePart := ppOrder;
+ else ParsePart := ppBogus;
+ end;
+
+ FWhereStartPos := PhraseP-PSQL+1;
PStatementPart := CurrentP;
+ end
+ else
+ // joined table or user_defined_function (...)
+ if (s = 'JOIN') or (Separator in [sepComma, sepParentheses]) then
+ begin
+ FTableName := '';
+ FUpdateable := False;
end;
end;
ppWhere : begin
- if (s = 'ORDER') or (s = 'GROUP') or (s = 'LIMIT') or (CurrentP^=#0) or (CurrentP^=';') then
+ if (s = 'GROUP') or (s = 'ORDER') or (s = 'LIMIT') or (s = 'ROWS') or
+ (Separator = sepEnd) then
begin
ParsePart := ppBogus;
FWhereStartPos := PStatementPart-PSQL;
- if (s = 'ORDER') or (s = 'GROUP') or (s = 'LIMIT') then
- FWhereStopPos := PhraseP-PSQL+1
+ if (Separator = sepEnd) then
+ FWhereStopPos := CurrentP-PSQL+1
else
- FWhereStopPos := CurrentP-PSQL+1;
+ FWhereStopPos := PhraseP-PSQL+1;
end
else if (s = 'UNION') then
begin
@@ -1371,6 +1368,8 @@ begin
end;
end; {case}
end;
+ if Separator in [sepComment, sepParentheses] then
+ dec(CurrentP);
PhraseP := CurrentP+1;
end
end;
@@ -1381,7 +1380,6 @@ procedure TCustomSQLQuery.InternalOpen;
var tel, fieldc : integer;
f : TField;
- s : string;
IndexFields : TStrings;
ReadFromFile: Boolean;
begin
diff --git a/mips/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp b/mips/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
index 1d7bc3a74e..c688ef9122 100644
--- a/mips/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
+++ b/mips/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp
@@ -831,6 +831,7 @@ function TSQLite3Connection.GetSchemaInfoSQL(SchemaType: TSchemaType;
begin
case SchemaType of
stTables : result := 'select name as table_name from sqlite_master where type = ''table'' order by 1';
+ stSysTables : result := 'select ''sqlite_master'' as table_name';
stColumns : result := 'pragma table_info(''' + (SchemaObjectName) + ''')';
else
DatabaseError(SMetadataUnavailable)
diff --git a/mips/packages/fcl-db/tests/bufdatasettoolsunit.pas b/mips/packages/fcl-db/tests/bufdatasettoolsunit.pas
index 0405650ae2..d40893d95e 100644
--- a/mips/packages/fcl-db/tests/bufdatasettoolsunit.pas
+++ b/mips/packages/fcl-db/tests/bufdatasettoolsunit.pas
@@ -37,6 +37,9 @@ type
implementation
+uses
+ StrUtils, FmtBCD;
+
type
{ TPersistentBufDataSet }
@@ -85,6 +88,7 @@ var BufDataset : TPersistentBufDataSet;
begin
BufDataset := TPersistentBufDataSet.Create(nil);
+ BufDataset.Name := 'NDataset';
BufDataset.FieldDefs.Add('ID',ftInteger);
BufDataset.FieldDefs.Add('NAME',ftString,50);
BufDataset.CreateDataset;
@@ -109,20 +113,20 @@ var BufDataset : TPersistentBufDataSet;
i : integer;
begin
- // Values >= 24:00:00.000 can't be handled by bufdataset
+ // Values >= 24:00:00.000 can't be handled by StrToTime function
testTimeValues[2] := '23:59:59.000';
testTimeValues[3] := '23:59:59.003';
BufDataset := TPersistentBufDataSet.Create(nil);
with BufDataset do
begin
+ Name := 'FieldDataset';
UniDirectional := FUniDirectional;
FieldDefs.Add('ID',ftInteger);
FieldDefs.Add('FSTRING',ftString,10);
FieldDefs.Add('FSMALLINT',ftSmallint);
FieldDefs.Add('FINTEGER',ftInteger);
- // Not supported by BufDataset:
- // FieldDefs.Add('FWORD',ftWord);
+ FieldDefs.Add('FWORD',ftWord);
FieldDefs.Add('FBOOLEAN',ftBoolean);
FieldDefs.Add('FFLOAT',ftFloat);
FieldDefs.Add('FCURRENCY',ftCurrency);
@@ -130,7 +134,11 @@ begin
FieldDefs.Add('FDATE',ftDate);
FieldDefs.Add('FTIME',ftTime);
FieldDefs.Add('FDATETIME',ftDateTime);
+ FieldDefs.Add('FBLOB',ftBlob);
+ FieldDefs.Add('FMEMO',ftMemo);
FieldDefs.Add('FLARGEINT',ftLargeint);
+ FieldDefs.Add('FFIXEDCHAR',ftFixedChar,10);
+ FieldDefs.Add('FFMTBCD',ftFmtBCD);
CreateDataset;
Open;
for i := 0 to testValuesCount-1 do
@@ -146,7 +154,12 @@ begin
FieldByName('FBCD').AsCurrency := testCurrencyValues[i];
FieldByName('FDATE').AsDateTime := StrToDateTime(testDateValues[i], Self.FormatSettings);
FieldByName('FTIME').AsDateTime := StrToTime(testTimeValues[i], Self.FormatSettings);
+ FieldByName('FDATETIME').AsDateTime := StrToDateTime(testValues[ftDateTime,i], Self.FormatSettings);
+ FieldByName('FBLOB').AsString := testStringValues[i];
+ FieldByName('FMEMO').AsString := testStringValues[i];
FieldByName('FLARGEINT').AsLargeInt := testLargeIntValues[i];
+ FieldByName('FFIXEDCHAR').AsString := PadRight(testStringValues[i], 10);
+ FieldByName('FFMTBCD').AsBCD := StrToBCD(testFmtBCDValues[i], Self.FormatSettings);
Post;
end;
BufDataset.TempFileName:=GetTempFileName;
diff --git a/mips/packages/fcl-db/tests/dbtestframework.pas b/mips/packages/fcl-db/tests/dbtestframework.pas
index 023270e040..8464bf93af 100644
--- a/mips/packages/fcl-db/tests/dbtestframework.pas
+++ b/mips/packages/fcl-db/tests/dbtestframework.pas
@@ -18,11 +18,12 @@ uses
memdstoolsunit,
SdfDSToolsUnit,
// Units wich contains the tests
- testbasics,
- testfieldtypes,
+ TestBasics,
+ TestFieldTypes,
TestDatasources,
- testdbbasics,
- TestBufDatasetStreams;
+ TestDBBasics,
+ TestBufDatasetStreams,
+ TestSpecificTBufDataset;
var
FXMLResultsWriter: TXMLResultsWriter;
diff --git a/mips/packages/fcl-db/tests/testbasics.pas b/mips/packages/fcl-db/tests/testbasics.pas
index 443b6d7693..04379791af 100644
--- a/mips/packages/fcl-db/tests/testbasics.pas
+++ b/mips/packages/fcl-db/tests/testbasics.pas
@@ -22,6 +22,8 @@ type
procedure TestInitFielddefsFromFields;
procedure TestDoubleFieldDef;
procedure TestFieldDefWithoutDS;
+ procedure TestGetParamList;
+ procedure TestGetFieldList;
procedure TestExtractFieldName;
end;
@@ -189,6 +191,130 @@ begin
FieldDefs.Free;
end;
+procedure TTestBasics.TestGetFieldList;
+var
+ ds: TDataSet;
+ F: TField;
+ List: TList;
+ ExceptionRaised: Boolean;
+begin
+ ds := TDataSet.Create(nil);
+ try
+ F := TIntegerField.Create(ds);
+ F.FieldName := 'Field1';
+ F.DataSet := ds;
+
+ F := TIntegerField.Create(ds);
+ F.FieldName := 'Field2';
+ F.DataSet := ds;
+
+ F := TIntegerField.Create(ds);
+ F.FieldName := 'Field3';
+ F.DataSet := ds;
+
+ List := TList.Create;
+ try
+ //should not
+ List.Clear;
+ ds.GetFieldList(List, '');
+ AssertEquals(0, List.Count);
+
+ List.Clear;
+ ExceptionRaised := False;
+ try
+ ds.GetFieldList(List, ' ');
+ except
+ on E: EDatabaseError do ExceptionRaised := True;
+ end;
+ AssertTrue(ExceptionRaised);
+
+ List.Clear;
+ ds.GetFieldList(List, 'Field1');
+ AssertEquals(1, List.Count);
+
+ List.Clear;
+ ds.GetFieldList(List, ' Field1 ');
+ AssertEquals(1, List.Count);
+
+ List.Clear;
+ ds.GetFieldList(List, 'Field1;Field2');
+ AssertEquals(2, List.Count);
+
+ List.Clear;
+ ds.GetFieldList(List, 'Field1;Field2;');
+ AssertEquals(2, List.Count);
+
+ List.Clear;
+ ds.GetFieldList(List, 'Field1;Field2;Field3');
+ AssertEquals(3, List.Count);
+ finally
+ List.Destroy;
+ end;
+ finally
+ ds.Destroy;
+ end;
+end;
+
+procedure TTestBasics.TestGetParamList;
+var
+ Params: TParams;
+ P: TParam;
+ List: TList;
+ ExceptionRaised: Boolean;
+begin
+ Params := TParams.Create(nil);
+ try
+ P := TParam.Create(Params, ptInput);
+ P.Name := 'Param1';
+
+ P := TParam.Create(Params, ptInput);
+ P.Name := 'Param2';
+
+ P := TParam.Create(Params, ptInput);
+ P.Name := 'Param3';
+
+ List := TList.Create;
+ try
+ List.Clear;
+ Params.GetParamList(List, '');
+ AssertEquals(0, List.Count);
+
+ List.Clear;
+ ExceptionRaised := False;
+ try
+ Params.GetParamList(List, ' ');
+ except
+ on E: EDatabaseError do ExceptionRaised := True;
+ end;
+ AssertTrue(ExceptionRaised);
+
+ List.Clear;
+ Params.GetParamList(List, 'Param1');
+ AssertEquals(1, List.Count);
+
+ List.Clear;
+ Params.GetParamList(List, ' Param1 ');
+ AssertEquals(1, List.Count);
+
+ List.Clear;
+ Params.GetParamList(List, 'Param1;');
+ AssertEquals(1, List.Count);
+
+ List.Clear;
+ Params.GetParamList(List, 'Param1;Param2');
+ AssertEquals(2, List.Count);
+
+ List.Clear;
+ Params.GetParamList(List, 'Param1;Param2;Param3');
+ AssertEquals(3, List.Count);
+ finally
+ List.Destroy;
+ end;
+ finally
+ Params.Destroy;
+ end;
+end;
+
procedure TTestBasics.TestExtractFieldName;
var
diff --git a/mips/packages/fcl-db/tests/testbufdatasetstreams.pas b/mips/packages/fcl-db/tests/testbufdatasetstreams.pas
index 93ef270648..c42fc15a24 100644
--- a/mips/packages/fcl-db/tests/testbufdatasetstreams.pas
+++ b/mips/packages/fcl-db/tests/testbufdatasetstreams.pas
@@ -69,6 +69,9 @@ type
procedure TestSeveralEditsXML;
procedure TestDeleteAllXML;
procedure TestDeleteAllInsertXML;
+ procedure TestStreamingBlobFieldsXML;
+ procedure TestStreamingBigBlobFieldsXML;
+ procedure TestStreamingCalculatedFieldsXML;
procedure TestAppendDeleteBIN;
@@ -452,6 +455,124 @@ begin
TestChangesXML(@DeleteAllInsertChange);
end;
+procedure TTestBufDatasetStreams.TestStreamingBlobFieldsXML;
+var SaveDs: TCustomBufDataset;
+ LoadDs: TCustomBufDataset;
+begin
+ SaveDs := DBConnector.GetFieldDataset as TCustomBufDataset;
+ SaveDs.Open;
+ SaveDs.SaveToFile('FieldsDS.xml',dfXML);
+
+ LoadDs := TCustomBufDataset.Create(nil);
+ LoadDs.LoadFromFile('FieldsDS.xml');
+
+ LoadDS.First;
+ SaveDS.First;
+ while not LoadDS.EOF do
+ begin
+ AssertEquals(LoadDS.FieldByName('FBLOB').AsString,SaveDS.FieldByName('FBLOB').AsString);
+ AssertEquals(LoadDS.FieldByName('FMEMO').AsString,SaveDS.FieldByName('FMEMO').AsString);
+ LoadDS.Next;
+ SaveDS.Next;
+ end;
+
+ LoadDs.Free;
+end;
+
+procedure TTestBufDatasetStreams.TestStreamingBigBlobFieldsXML;
+var
+ SaveDs: TCustomBufDataset;
+ LoadDs: TCustomBufDataset;
+ j: integer;
+ i: byte;
+ s: string;
+ f: file of byte;
+ fn: string;
+ fs: TMemoryStream;
+begin
+ // Create a temp. file with blob-data.
+ fn := GetTempFileName;
+ assign(f,fn);
+ Rewrite(f);
+ s := 'This is a blob-field test file.';
+ for j := 0 to 250 do
+ begin
+ for i := 1 to length(s) do
+ write(f,ord(s[i]));
+ for i := 0 to 255 do
+ write(f,i);
+ end;
+ close(f);
+
+ try
+ // Open dataset and set blob-field-data to content of blob-file.
+ SaveDs := DBConnector.GetFieldDataset(true) as TCustomBufDataset;
+ SaveDs.Open;
+ SaveDs.Edit;
+ TBlobField(SaveDs.FieldByName('FBLOB')).LoadFromFile(fn);
+ SaveDs.Post;
+
+ // Save this dataset to file.
+ SaveDs.SaveToFile('FieldsDS.xml',dfXML);
+
+ // Load this file in another dataset
+ LoadDs := TCustomBufDataset.Create(nil);
+ try
+ LoadDs.LoadFromFile('FieldsDS.xml');
+ LoadDS.First;
+
+ // Compare the content of the blob-field with the file on disc
+ fs := TMemoryStream.Create;
+ try
+ TBlobField(SaveDs.FieldByName('FBLOB')).SaveToStream(fs);
+ fs.Seek(0,soBeginning);
+ assign(f,fn);
+ reset(f);
+ for j := 0 to fs.Size-1 do
+ begin
+ read(f,i);
+ CheckEquals(i,fs.ReadByte);
+ end;
+ finally
+ fs.free;
+ end;
+ finally
+ LoadDs.Free;
+ end;
+ finally
+ DeleteFile(fn);
+ end;
+end;
+
+procedure TTestBufDatasetStreams.TestStreamingCalculatedFieldsXML;
+var
+ ADataset: TCustomBufDataset;
+ f: tfield;
+begin
+ ADataset := DBConnector.GetNDataset(true,10) as TCustomBufDataset;
+ f := TIntegerField.Create(ADataset);
+ f.FieldName:='ID';
+ f.dataset := ADataset;
+
+ f := TIntegerField.Create(ADataset);
+ f.FieldName:='CalcID';
+ f.dataset := ADataset;
+ f.FieldKind:=fkCalculated;
+
+ f := TStringField.Create(ADataset);
+ f.FieldName:='NAME';
+ f.dataset := ADataset;
+
+ ADataset.Open;
+ ADataset.SaveToFile('FieldsDS.xml',dfXML);
+ ADataset.Close;
+
+ ADataset.LoadFromFile('FieldsDS.xml',dfXML);
+ AssertEquals(ADataset.FieldByName('ID').AsInteger,1);
+ AssertEquals(ADataset.FieldByName('NAME').AsString,'TestName1');
+ ADataset.Close;
+end;
+
procedure TTestBufDatasetStreams.TestAppendDeleteBIN;
begin
TestChanges(@AppendDeleteChange);
diff --git a/mips/packages/fcl-db/tests/testdbbasics.pas b/mips/packages/fcl-db/tests/testdbbasics.pas
index fb8aeab5d0..dedc12e737 100644
--- a/mips/packages/fcl-db/tests/testdbbasics.pas
+++ b/mips/packages/fcl-db/tests/testdbbasics.pas
@@ -42,6 +42,8 @@ type
procedure TestSupportBCDFields;
procedure TestSupportfmtBCDFields;
procedure TestSupportFixedStringFields;
+ procedure TestSupportBlobFields;
+ procedure TestSupportMemoFields;
procedure TestDoubleClose;
procedure TestCalculatedField;
@@ -58,6 +60,7 @@ type
procedure TestdeFieldListChange;
procedure TestExceptionLocateClosed; // bug 13938
procedure TestCanModifySpecialFields;
+ procedure TestDetectionNonMatchingDataset;
end;
{ TTestBufDatasetDBBasics }
@@ -677,12 +680,39 @@ begin
CheckFalse(FieldByName('LookupFld').ReadOnly);
CheckEquals(1,FieldByName('ID').AsInteger);
- CheckEquals('name1',FieldByName('LookupFld').AsString);
- close;
+ CheckEquals('TestName1',FieldByName('LookupFld').AsString);
+ Next;
+ Next;
+ CheckEquals(3,FieldByName('ID').AsInteger);
+ CheckEquals('TestName3',FieldByName('LookupFld').AsString);
+
+ Close;
lds.Close;
end;
end;
+procedure TTestDBBasics.TestDetectionNonMatchingDataset;
+var
+ F: TField;
+ ds: tdataset;
+begin
+ // TDataset.Bindfields should detect problems when the underlying data does
+ // not reflect the fields of the dataset. This test is to check if this is
+ // really done.
+ ds := DBConnector.GetNDataset(true,6);
+ with ds do
+ begin
+ open;
+ close;
+
+ F := TStringField.Create(ds);
+ F.FieldName:='DOES_NOT_EXIST';
+ F.DataSet:=ds;
+ F.Size:=50;
+
+ CheckException(open,EDatabaseError);
+ end;
+end;
procedure TTestCursorDBBasics.TestAppendInsertRecord;
begin
@@ -2359,6 +2389,37 @@ begin
ds.close;
end;
+procedure TTestDBBasics.TestSupportBlobFields;
+
+var i : byte;
+ ds : TDataset;
+ Fld : TField;
+begin
+ TestfieldDefinition(ftBlob,0,ds,Fld);
+
+ for i := 0 to testValuesCount-1 do
+ begin
+ CheckEquals(testValues[ftBlob,i],Fld.AsString);
+ ds.Next;
+ end;
+ ds.close;
+end;
+
+procedure TTestDBBasics.TestSupportMemoFields;
+var i : byte;
+ ds : TDataset;
+ Fld : TField;
+begin
+ TestfieldDefinition(ftMemo,0,ds,Fld);
+
+ for i := 0 to testValuesCount-1 do
+ begin
+ CheckEquals(testValues[ftMemo,i],Fld.AsString);
+ ds.Next;
+ end;
+ ds.close;
+end;
+
procedure TTestDBBasics.TestDoubleClose;
begin
with DBConnector.GetNDataset(1) do
diff --git a/mips/packages/fcl-db/tests/testfieldtypes.pas b/mips/packages/fcl-db/tests/testfieldtypes.pas
index cc173501e2..73cdb65421 100644
--- a/mips/packages/fcl-db/tests/testfieldtypes.pas
+++ b/mips/packages/fcl-db/tests/testfieldtypes.pas
@@ -38,7 +38,7 @@ type
procedure TestInsertLargeStrFields; // bug 9600
procedure TestNumericNames; // Bug9661
procedure TestApplyUpdFieldnames; // Bug 12275;
- procedure TestLimitQuery; // bug 15456
+ procedure TestServerFilter; // bug 15456
procedure Test11Params;
procedure TestRowsAffected; // bug 9758
procedure TestLocateNull;
@@ -1438,7 +1438,13 @@ begin
begin
SQL.Text:='select TT.NAME from FPDEV left join FPDEV TT on TT.ID=FPDEV.ID';
Open;
- close;
+ AssertFalse(CanModify);
+ Close;
+
+ SQL.Text:='select T1.NAME from FPDEV T1,FPDEV T2 where T1.ID=T2.ID';
+ Open;
+ AssertFalse(CanModify);
+ Close;
end;
end;
end;
@@ -1565,25 +1571,57 @@ begin
end;
end;
-procedure TTestFieldTypes.TestLimitQuery;
+procedure TTestFieldTypes.TestServerFilter;
begin
- with TSQLDBConnector(DBConnector) do
- begin
- with query do
- begin
- case sqlDBtype of
- interbase : SQL.Text:='select first 1 NAME from FPDEV where NAME=''TestName21''';
- mssql : SQL.Text:='select top 1 NAME from FPDEV where NAME=''TestName21''';
- else SQL.Text:='select NAME from FPDEV where NAME=''TestName21'' limit 1';
- end;
- Open;
- close;
- ServerFilter:='ID=21';
- ServerFiltered:=true;
- open;
- close;
- end;
+ // Tests SQLParser and ServerFilter
+ with TSQLDBConnector(DBConnector).Query do
+ begin
+ ServerFilter:='ID=21';
+ ServerFiltered:=true;
+
+ // tests parsing SELECT without WHERE
+ SQL.Text:='select * from FPDEV';
+ Open;
+ CheckTrue(CanModify, SQL.Text);
+ CheckEquals(1, RecordCount);
+ Close;
+
+ SQL.Text:='select *'#13'from FPDEV'#13'order by 1';
+ Open;
+ CheckTrue(CanModify, SQL.Text);
+ CheckEquals(1, RecordCount);
+ Close;
+
+ // tests parsing SELECT with simple WHERE
+ SQL.Text:='select *'#9'from FPDEV'#9'where NAME<>''''';
+ Open;
+ CheckTrue(CanModify, SQL.Text);
+ CheckEquals(1, RecordCount);
+ Close;
+
+ // tests parsing SELECT with simple WHERE followed by ORDER BY
+ SQL.Text:='select *'#10'from FPDEV'#10'where NAME>'''' order by 1';
+ Open;
+ CheckTrue(CanModify, SQL.Text);
+ CheckEquals(1, RecordCount);
+ Close;
+
+ // tests parsing of WHERE ... LIMIT
+ case sqlDBtype of
+ interbase : SQL.Text:='select first 1 NAME from FPDEV where NAME=''TestName21''';
+ mssql : SQL.Text:='select top 1 NAME from FPDEV where NAME=''TestName21''';
+ else SQL.Text:='select NAME from FPDEV where NAME=''TestName21'' limit 1';
end;
+ Open;
+ CheckTrue(CanModify, SQL.Text);
+ Close;
+
+ // tests parsing SELECT with table alias and embedded comments (MySQL requires space after -- )
+ SQL.Text:='/**/select * from/**/FPDEV as fp-- comment'#13'where(NAME>''TestName20'')/**/order by 1';
+ Open;
+ CheckTrue(CanModify, SQL.Text);
+ Close;
+ end;
end;
procedure TTestFieldTypes.TestRowsAffected;
diff --git a/mips/packages/fcl-db/tests/testspecifictbufdataset.pas b/mips/packages/fcl-db/tests/testspecifictbufdataset.pas
index 93b9108d34..49866cb224 100644
--- a/mips/packages/fcl-db/tests/testspecifictbufdataset.pas
+++ b/mips/packages/fcl-db/tests/testspecifictbufdataset.pas
@@ -25,7 +25,9 @@ type
TTestSpecificTBufDataset = class(TTestCase)
private
- procedure TestDataset(ABufDataset: TBufDataset);
+ procedure TestDataset(ABufDataset: TBufDataset; AutoInc: boolean = false);
+ function GetAutoIncDataset: TBufDataset;
+ procedure IntTestAutoIncFieldStreaming(XML: boolean);
protected
procedure SetUp; override;
procedure TearDown; override;
@@ -33,6 +35,10 @@ type
procedure CreateDatasetFromFielddefs;
procedure CreateDatasetFromFields;
procedure TestOpeningNonExistingDataset;
+ procedure TestCreationDatasetWithCalcFields;
+ procedure TestAutoIncField;
+ procedure TestAutoIncFieldStreaming;
+ procedure TestAutoIncFieldStreamingXML;
end;
implementation
@@ -47,14 +53,16 @@ uses
{ TTestSpecificTBufDataset }
-procedure TTestSpecificTBufDataset.TestDataset(ABufDataset: TBufDataset);
+procedure TTestSpecificTBufDataset.TestDataset(ABufDataset: TBufDataset;
+ AutoInc: boolean);
var
i : integer;
begin
for i := 1 to 10 do
begin
ABufDataset.Append;
- ABufDataset.FieldByName('ID').AsInteger := i;
+ if not AutoInc then
+ ABufDataset.FieldByName('ID').AsInteger := i;
ABufDataset.FieldByName('NAME').AsString := 'TestName' + inttostr(i);
ABufDataset.Post;
end;
@@ -68,6 +76,52 @@ begin
CheckTrue(ABufDataset.EOF);
end;
+function TTestSpecificTBufDataset.GetAutoIncDataset: TBufDataset;
+var
+ ds : TBufDataset;
+ f: TField;
+begin
+ ds := TBufDataset.Create(nil);
+ F := TAutoIncField.Create(ds);
+ F.FieldName:='ID';
+ F.DataSet:=ds;
+ F := TStringField.Create(ds);
+ F.FieldName:='NAME';
+ F.DataSet:=ds;
+ F.Size:=50;
+ DS.CreateDataset;
+
+ TestDataset(ds,True);
+ result := ds;
+end;
+
+procedure TTestSpecificTBufDataset.IntTestAutoIncFieldStreaming(XML: boolean);
+var
+ ds : TBufDataset;
+ fn: string;
+begin
+ ds := GetAutoIncDataset;
+ fn := GetTempFileName;
+ if xml then
+ ds.SaveToFile(fn,dfXML)
+ else
+ ds.SaveToFile(fn);
+ DS.Close;
+ ds.Free;
+
+ ds := TBufDataset.Create(nil);
+ ds.LoadFromFile(fn);
+ ds.Last;
+ CheckEquals(10,ds.FieldByName('Id').AsInteger);
+ ds.Append;
+ ds.FieldByName('NAME').asstring := 'Test';
+ ds.Post;
+ CheckEquals(11,ds.FieldByName('Id').AsInteger);
+ ds.Free;
+
+ DeleteFile(fn);
+end;
+
procedure TTestSpecificTBufDataset.SetUp;
begin
DBConnector.StartTest;
@@ -129,6 +183,71 @@ begin
ds.Free;
end;
+procedure TTestSpecificTBufDataset.TestCreationDatasetWithCalcFields;
+var ds : TBufDataset;
+ f: TField;
+ i: integer;
+begin
+ ds := TBufDataset.Create(nil);
+ try
+ F := TIntegerField.Create(ds);
+ F.FieldName:='ID';
+ F.DataSet:=ds;
+ F := TStringField.Create(ds);
+ F.FieldName:='NAME';
+ F.DataSet:=ds;
+ F.Size:=50;
+
+ F := TStringField.Create(ds);
+ F.FieldKind:=fkCalculated;
+ F.FieldName:='NAME_CALC';
+ F.DataSet:=ds;
+ F.Size:=50;
+
+ F := TStringField.Create(ds);
+ F.FieldKind:=fkLookup;
+ F.FieldName:='NAME_LKP';
+ F.LookupDataSet:=DBConnector.GetNDataset(5);
+ F.KeyFields:='ID';
+ F.LookupKeyFields:='ID';
+ F.LookupResultField:='NAME';
+ F.DataSet:=ds;
+ F.Size:=50;
+
+ DS.CreateDataset;
+
+ TestDataset(ds);
+
+ for i := 0 to ds.FieldDefs.Count-1 do
+ begin
+ CheckNotEquals(ds.FieldDefs[i].Name,'NAME_CALC');
+ CheckNotEquals(ds.FieldDefs[i].Name,'NAME_LKP');
+ end;
+ DS.Close;
+ finally
+ ds.Free;
+ end;
+end;
+
+procedure TTestSpecificTBufDataset.TestAutoIncField;
+var
+ ds : TBufDataset;
+begin
+ ds := GetAutoIncDataset;
+ DS.Close;
+ ds.Free;
+end;
+
+procedure TTestSpecificTBufDataset.TestAutoIncFieldStreaming;
+begin
+ IntTestAutoIncFieldStreaming(false);
+end;
+
+procedure TTestSpecificTBufDataset.TestAutoIncFieldStreamingXML;
+begin
+ IntTestAutoIncFieldStreaming(true);
+end;
+
initialization
{$ifdef fpc}
diff --git a/mips/packages/fcl-db/tests/toolsunit.pas b/mips/packages/fcl-db/tests/toolsunit.pas
index 548c857c2c..bdbb494573 100644
--- a/mips/packages/fcl-db/tests/toolsunit.pas
+++ b/mips/packages/fcl-db/tests/toolsunit.pas
@@ -311,6 +311,8 @@ begin
testValues[ftFixedChar] := testStringValues;
testValues[ftTime] := testTimeValues;
testValues[ftDate] := testDateValues;
+ testValues[ftBlob] := testStringValues;
+ testValues[ftMemo] := testStringValues;
testValues[ftFMTBcd] := testFmtBCDValues;
for i := 0 to testValuesCount-1 do
begin
diff --git a/mips/packages/fcl-fpcunit/src/fpcunit.pp b/mips/packages/fcl-fpcunit/src/fpcunit.pp
index 07a1ee1696..ce7cd5b23f 100644
--- a/mips/packages/fcl-fpcunit/src/fpcunit.pp
+++ b/mips/packages/fcl-fpcunit/src/fpcunit.pp
@@ -19,22 +19,10 @@ unit fpcunit;
interface
-{ The following is wrong. The lineinfo unit only works on platforms that
- use stabs. It does not work on platforms that use stabx or Dwarf. The
- correct unit can only be safely included by compiling the main program
- with -gl. Directly using any of those units won't work most of the time.
-}
-{$IF not defined(MORPHOS) and not defined(AIX)}
- {$DEFINE SHOWLINEINFO}
-{$ENDIF}
-
{ Uncomment this define to remove the DUnit compatibility interface. }
{$DEFINE DUnit}
uses
- {$ifdef SHOWLINEINFO}
- LineInfo,
- {$endif}
SysUtils
,Classes
;
diff --git a/mips/packages/fcl-image/examples/Makefile b/mips/packages/fcl-image/examples/Makefile
index c4a95daf72..e7d04919b2 100644
--- a/mips/packages/fcl-image/examples/Makefile
+++ b/mips/packages/fcl-image/examples/Makefile
@@ -1,8 +1,8 @@
#
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/04/25]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/06/18]
#
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 powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux
+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 powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux jvm-java jvm-android
BSDs = freebsd netbsd openbsd darwin
UNIXs = linux $(BSDs) solaris qnx haiku aix
LIMIT83fs = go32v2 os2 emx watcom
@@ -258,11 +258,13 @@ ifndef BINUTILSPREFIX
ifndef CROSSBINDIR
ifdef CROSSCOMPILE
ifndef DARWIN2DARWIN
+ifneq ($(CPU_TARGET),jvm)
BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
endif
endif
endif
endif
+endif
UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
ifeq ($(UNITSDIR),)
UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
@@ -293,208 +295,214 @@ FPCFPMAKE=$(FPC)
endif
endif
ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_PROGRAMS+=imgconv drawing xwdtobmp
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
+endif
+ifeq ($(FULL_TARGET),jvm-java)
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+override TARGET_PROGRAMS+=imgconv drawing xwdtobmp interpoldemo
endif
override INSTALL_FPCPACKAGE=y
ifdef REQUIRE_UNITSDIR
@@ -854,6 +862,18 @@ BATCHEXT=.sh
EXEEXT=
SHORTSUFFIX=aix
endif
+ifeq ($(OS_TARGET),java)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=java
+endif
+ifeq ($(OS_TARGET),android)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=android
+endif
ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
FPCMADE=fpcmade.$(SHORTSUFFIX)
ZIPSUFFIX=$(SHORTSUFFIX)
@@ -1640,6 +1660,22 @@ REQUIRE_PACKAGES_HASH=1
REQUIRE_PACKAGES_FPMKUNIT=1
REQUIRE_PACKAGES_FCL-IMAGE=1
endif
+ifeq ($(FULL_TARGET),jvm-java)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-IMAGE=1
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-IMAGE=1
+endif
ifdef REQUIRE_PACKAGES_RTL
PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
ifneq ($(PACKAGEDIR_RTL),)
@@ -1980,17 +2016,12 @@ 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
diff --git a/mips/packages/fcl-image/examples/Makefile.fpc b/mips/packages/fcl-image/examples/Makefile.fpc
index 3a6ad2d8fe..aeebf608cb 100644
--- a/mips/packages/fcl-image/examples/Makefile.fpc
+++ b/mips/packages/fcl-image/examples/Makefile.fpc
@@ -3,7 +3,7 @@
#
[target]
-programs=imgconv drawing xwdtobmp
+programs=imgconv drawing xwdtobmp interpoldemo
[require]
packages=fcl-image
diff --git a/mips/packages/fcl-image/examples/drawing.pp b/mips/packages/fcl-image/examples/drawing.pp
index 4a50fc8a68..518e867b43 100644
--- a/mips/packages/fcl-image/examples/drawing.pp
+++ b/mips/packages/fcl-image/examples/drawing.pp
@@ -2,7 +2,7 @@
program Drawing;
uses classes, sysutils,
- FPImage, FPCanvas, FPImgCanv,
+ FPImage, FPCanvas, FPImgCanv, ftFont,
FPWritePNG, FPReadPNG;
const
@@ -13,6 +13,7 @@ var canvas : TFPcustomCAnvas;
ci, image : TFPCustomImage;
writer : TFPCustomImageWriter;
reader : TFPCustomImageReader;
+ f : TFreeTypeFont;
begin
image := TFPMemoryImage.Create (100,100);
ci := TFPMemoryImage.Create (20,20);
@@ -27,7 +28,7 @@ begin
GrayScale := false;
end;
try
- ci.LoadFromFile ('test.png', reader);
+// ci.LoadFromFile ('test.png', reader);
with Canvas as TFPImageCanvas do
begin
pen.mode := pmCopy;
@@ -51,11 +52,13 @@ begin
end;
pen.style := psSolid;
RelativeBrushImage := true;
+{
brush.image := ci;
brush.style := bsimage;
with brush.FPColor do
green := green div 2;
Ellipse (11,11, 89,89);
+}
brush.style := bsSolid;
brush.FPColor := MyColor;
@@ -68,8 +71,19 @@ begin
pen.FPColor := colCyan;
ellipseC (50,50, 1,1);
- writeln ('Saving to inspect !');
+ InitEngine;
+ F:=TFreeTypeFont.Create;
+ F.Angle:=0.15;
+ Font:=F;
+// Font.Name:='/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf';
+ Font.Name:='/home/michael/Documents/arial.ttf';
+ Font.Size:=10;
+ Font.FPColor:=colWhite;
+// Font.Orientation:=900;
+
+ Canvas.TextOut(10,90,'o');
end;
+ writeln ('Saving to inspect !');
image.SaveToFile ('DrawTest.png', writer);
finally
Canvas.Free;
@@ -81,7 +95,7 @@ begin
end;
begin
- // DefaultFontPath := 'c:\winnt\fonts\';
+// DefaultFontPath := '/usr/share/fonts/truetype/ttf-dejavu/';
DoDraw;
end.
diff --git a/mips/packages/fcl-image/examples/interpoldemo.pp b/mips/packages/fcl-image/examples/interpoldemo.pp
new file mode 100644
index 0000000000..13fed448b9
--- /dev/null
+++ b/mips/packages/fcl-image/examples/interpoldemo.pp
@@ -0,0 +1,39 @@
+program interpoldemo;
+// Interpolation demo for fcl-image by Bernd Kreuss. Mantis #22245
+// Loads original.png (not included) and scales it back to 64x64
+
+{$mode objfpc}{$H+}
+
+uses
+ Classes,
+ sysutils,
+ FPimage,
+ FPImgCanv,
+ FPReadPNG,
+ FPWritePNG;
+
+var
+ ImOriginal: TFPMemoryImage;
+ ImScaled: TFPMemoryImage;
+ CanvScaled: TFPImageCanvas;
+ Reader: TFPReaderPNG;
+ Writer: TFPWriterPNG;
+
+begin
+ ImOriginal := TFPMemoryImage.Create(0, 0);
+ ImScaled := TFPMemoryImage.Create(64, 64);
+ Reader := TFPReaderPNG.create;
+ Writer := TFPWriterPNG.create;
+ Writer.UseAlpha := True;
+ ImOriginal.LoadFromFile('original.png', Reader);
+
+ CanvScaled := TFPImageCanvas.create(ImScaled);
+ CanvScaled.StretchDraw(0,0,63,63, ImOriginal);
+
+ ImScaled.SaveToFile('scaled.png', Writer);
+ Reader.Free;
+ Writer.Free;
+ ImOriginal.Free;
+ ImScaled.Free;
+end.
+
diff --git a/mips/packages/fcl-image/fpmake.pp b/mips/packages/fcl-image/fpmake.pp
index f8dcfc0eb7..afaad2723d 100644
--- a/mips/packages/fcl-image/fpmake.pp
+++ b/mips/packages/fcl-image/fpmake.pp
@@ -87,6 +87,7 @@ begin
AddInclude('fphandler.inc');
AddInclude('fppalette.inc');
AddInclude('fpcolcnv.inc');
+ AddInclude('fpcompactimg.inc');
end;
T:=P.Targets.AddUnit('fpimgcanv.pp');
with T.Dependencies do
@@ -260,7 +261,10 @@ begin
AddUnit('fpcanvas');
end;
T:=P.Targets.AddUnit('targacmn.pp');
-
+ T:=P.Targets.AddUnit('fpimggauss.pp');
+ With T.Dependencies do
+ AddUnit('fpimage');
+
P.ExamplePath.Add('examples');
T:=P.Targets.AddExampleProgram('drawing.pp');
T:=P.Targets.AddExampleProgram('imgconv.pp');
diff --git a/mips/packages/fcl-image/src/fpcompactimg.inc b/mips/packages/fcl-image/src/fpcompactimg.inc
new file mode 100644
index 0000000000..6140962b4e
--- /dev/null
+++ b/mips/packages/fcl-image/src/fpcompactimg.inc
@@ -0,0 +1,597 @@
+{%MainUnit fpimage.pp}
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2012 by the Free Pascal development team
+
+ Compact images (images with less than 64-bit depth) support, by Mattias Gaertner
+
+ 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.
+
+ **********************************************************************}
+
+function GetFPCompactImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean
+ ): TFPCompactImgDesc;
+begin
+ Result.Gray:=Gray;
+ Result.Depth:=Depth;
+ Result.HasAlpha:=HasAlpha;
+end;
+
+function GetFPCompactImgClass(const Desc: TFPCompactImgDesc): TFPCompactImgBaseClass;
+begin
+ if Desc.Gray then begin
+ if Desc.HasAlpha then begin
+ // gray, alpha
+ if Desc.Depth<=8 then
+ Result:=TFPCompactImgGrayAlpha8Bit
+ else
+ Result:=TFPCompactImgGrayAlpha16Bit;
+ end else begin
+ // gray, no alpha
+ if Desc.Depth<=8 then
+ Result:=TFPCompactImgGray8Bit
+ else
+ Result:=TFPCompactImgGray16Bit;
+ end;
+ end else begin
+ // RGB
+ if Desc.HasAlpha then begin
+ // RGB, alpha
+ if Desc.Depth<=8 then
+ Result:=TFPCompactImgRGBA8Bit
+ else
+ Result:=TFPCompactImgRGBA16Bit;
+ end else begin
+ // RGB, no alpha
+ if Desc.Depth<=8 then
+ Result:=TFPCompactImgRGB8Bit
+ else
+ Result:=TFPCompactImgRGB16Bit;
+ end;
+ end;
+end;
+
+function CreateFPCompactImg(const Desc: TFPCompactImgDesc; Width, Height: integer
+ ): TFPCustomImage;
+var
+ ImgClass: TFPCompactImgBaseClass;
+begin
+ ImgClass:=GetFPCompactImgClass(Desc);
+ Result:=ImgClass.Create(Width,Height);
+end;
+
+function CreateCompatibleFPCompactImg(Img: TFPCustomImage; Width, Height: integer
+ ): TFPCustomImage;
+begin
+ if Img is TFPCompactImgBase then
+ Result:=CreateFPCompactImg(TFPCompactImgBase(Img).Desc,Width,Height)
+ else
+ Result:=CreateFPCompactImg(GetMinimumPTDesc(Img),Width,Height);
+end;
+
+function CreateCompatibleFPCompactImgWithAlpha(Img: TFPCustomImage; Width,
+ Height: integer): TFPCustomImage;
+var
+ Desc: TFPCompactImgDesc;
+begin
+ if Img is TFPCompactImgBase then
+ Desc:=TFPCompactImgBase(Img).Desc
+ else
+ Desc:=GetMinimumPTDesc(Img);
+ Desc.HasAlpha:=true;
+ Result:=CreateFPCompactImg(Desc,Width,Height);
+end;
+
+function GetMinimumPTDesc(Img: TFPCustomImage; FuzzyDepth: word = 4): TFPCompactImgDesc;
+var
+ AllLoEqualsHi, AllLoAre0: Boolean;
+ FuzzyMaskLoHi: Word;
+
+ procedure Need16Bit(c: word); inline;
+ var
+ l: Byte;
+ begin
+ c:=c and FuzzyMaskLoHi;
+ l:=Lo(c);
+ AllLoAre0:=AllLoAre0 and (l=0);
+ AllLoEqualsHi:=AllLoEqualsHi and (l=Hi(c));
+ end;
+
+var
+ TestGray: Boolean;
+ TestAlpha: Boolean;
+ Test16Bit: Boolean;
+ BaseImg: TFPCompactImgBase;
+ ImgDesc: TFPCompactImgDesc;
+ y: Integer;
+ x: Integer;
+ col: TFPColor;
+ FuzzyMaskWord: Word;
+ FuzzyOpaque: Word;
+begin
+ TestGray:=true;
+ TestAlpha:=true;
+ Test16Bit:=FuzzyDepth<8;
+ Result.HasAlpha:=false;
+ Result.Gray:=true;
+ Result.Depth:=8;
+ if Img is TFPCompactImgBase then begin
+ BaseImg:=TFPCompactImgBase(Img);
+ ImgDesc:=BaseImg.Desc;
+ if ImgDesc.Depth<=8 then Test16Bit:=false;
+ if ImgDesc.Gray then TestGray:=false;
+ if not ImgDesc.HasAlpha then TestAlpha:=false;
+ end;
+
+ if (not TestGray) and (not TestAlpha) and (not Test16Bit) then exit;
+
+ FuzzyMaskWord:=Word($ffff) shl FuzzyDepth;
+ FuzzyOpaque:=alphaOpaque and FuzzyMaskWord;
+ FuzzyMaskLoHi:=Word(lo(FuzzyMaskWord))+(Word(lo(FuzzyMaskWord)) shl 8);
+ AllLoAre0:=true;
+ AllLoEqualsHi:=true;
+ for y:=0 to Img.Height-1 do begin
+ for x:=0 to Img.Width-1 do begin
+ col:=Img.Colors[x,y];
+ if TestAlpha and ((col.alpha and FuzzyMaskWord)<>FuzzyOpaque) then begin
+ TestAlpha:=false;
+ Result.HasAlpha:=true;
+ if (not TestGray) and (not Test16Bit) then break;
+ end;
+ if TestGray
+ and ((col.red and FuzzyMaskWord)<>(col.green and FuzzyMaskWord))
+ or ((col.red and FuzzyMaskWord)<>(col.blue and FuzzyMaskWord)) then begin
+ TestGray:=false;
+ Result.Gray:=false;
+ if (not TestAlpha) and (not Test16Bit) then break;
+ end;
+ if Test16Bit then begin
+ Need16Bit(col.red);
+ Need16Bit(col.green);
+ Need16Bit(col.blue);
+ Need16Bit(col.alpha);
+ if (not AllLoAre0) and (not AllLoEqualsHi) then begin
+ Test16Bit:=false;
+ Result.Depth:=16;
+ if (not TestAlpha) and (not TestGray) then break;
+ end;
+ end;
+ end;
+ end;
+end;
+
+function GetMinimumFPCompactImg(Img: TFPCustomImage; FreeImg: boolean;
+ FuzzyDepth: word = 4): TFPCustomImage;
+var
+ Desc: TFPCompactImgDesc;
+ ImgClass: TFPCompactImgBaseClass;
+ y: Integer;
+ x: Integer;
+begin
+ Desc:=GetMinimumPTDesc(Img,FuzzyDepth);
+ ImgClass:=GetFPCompactImgClass(Desc);
+ if Img.ClassType=ImgClass then
+ exit(Img);
+ Result:=CreateFPCompactImg(Desc,Img.Width,Img.Height);
+ for y:=0 to Img.Height-1 do
+ for x:=0 to Img.Width-1 do
+ Result.Colors[x,y]:=Img.Colors[x,y];
+ if FreeImg then
+ Img.Free;
+end;
+
+function ColorRound (c : double) : word;
+begin
+ if c > $FFFF then
+ result := $FFFF
+ else if c < 0.0 then
+ result := 0
+ else
+ result := round(c);
+end;
+
+{ TFPCompactImgGrayAlpha16Bit }
+
+function TFPCompactImgGrayAlpha16Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+ v: TFPCompactImgGrayAlpha16BitValue;
+begin
+ v:=FData[x+y*Width];
+ Result.red:=v.g;
+ Result.green:=Result.red;
+ Result.blue:=Result.red;
+ Result.alpha:=v.a;
+end;
+
+function TFPCompactImgGrayAlpha16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgGrayAlpha16Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+var
+ v: TFPCompactImgGrayAlpha16BitValue;
+begin
+ v.g:=Value.red;
+ v.a:=Value.alpha;
+ FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgGrayAlpha16Bit.SetInternalPixel(x, y: integer; Value: integer
+ );
+begin
+
+end;
+
+constructor TFPCompactImgGrayAlpha16Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(true,16,true);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGrayAlpha16Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgGrayAlpha16Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(TFPCompactImgGrayAlpha16BitValue)*AWidth*AHeight);
+ inherited SetSize(AWidth, AHeight);
+end;
+
+{ TFPCompactImgGrayAlpha8Bit }
+
+function TFPCompactImgGrayAlpha8Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+ v: TFPCompactImgGrayAlpha8BitValue;
+begin
+ v:=FData[x+y*Width];
+ Result.red:=(v.g shl 8)+v.g;
+ Result.green:=Result.red;
+ Result.blue:=Result.red;
+ Result.alpha:=(v.a shl 8)+v.a;
+end;
+
+function TFPCompactImgGrayAlpha8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgGrayAlpha8Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+var
+ v: TFPCompactImgGrayAlpha8BitValue;
+begin
+ v.g:=Value.red shr 8;
+ v.a:=Value.alpha shr 8;
+ FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgGrayAlpha8Bit.SetInternalPixel(x, y: integer; Value: integer
+ );
+begin
+
+end;
+
+constructor TFPCompactImgGrayAlpha8Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(true,8,true);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGrayAlpha8Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgGrayAlpha8Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(TFPCompactImgGrayAlpha8BitValue)*AWidth*AHeight);
+ inherited SetSize(AWidth, AHeight);
+end;
+
+{ TFPCompactImgGray16Bit }
+
+function TFPCompactImgGray16Bit.GetInternalColor(x, y: integer): TFPColor;
+begin
+ Result.red:=FData[x+y*Width];
+ Result.green:=Result.red;
+ Result.blue:=Result.red;
+ Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgGray16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgGray16Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+begin
+ FData[x+y*Width]:=Value.red;
+end;
+
+procedure TFPCompactImgGray16Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgGray16Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(true,16,false);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGray16Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgGray16Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(Word)*AWidth*AHeight);
+ inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgGray8Bit }
+
+function TFPCompactImgGray8Bit.GetInternalColor(x, y: integer): TFPColor;
+begin
+ Result.red:=FData[x+y*Width];
+ Result.red:=(Word(Result.red) shl 8)+Result.red;
+ Result.green:=Result.red;
+ Result.blue:=Result.red;
+ Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgGray8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgGray8Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+begin
+ FData[x+y*Width]:=Value.red shr 8;
+end;
+
+procedure TFPCompactImgGray8Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgGray8Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(true,8,false);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgGray8Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgGray8Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(Byte)*AWidth*AHeight);
+ inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGBA8Bit }
+
+function TFPCompactImgRGBA8Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+ v: TFPCompactImgRGBA8BitValue;
+begin
+ v:=FData[x+y*Width];
+ Result.red:=(v.r shl 8)+v.r;
+ Result.green:=(v.g shl 8)+v.g;
+ Result.blue:=(v.b shl 8)+v.b;
+ Result.alpha:=(v.a shl 8)+v.a;
+end;
+
+function TFPCompactImgRGBA8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgRGBA8Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+var
+ v: TFPCompactImgRGBA8BitValue;
+begin
+ v.r:=Value.red shr 8;
+ v.g:=Value.green shr 8;
+ v.b:=Value.blue shr 8;
+ v.a:=Value.alpha shr 8;
+ FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgRGBA8Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGBA8Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(false,8,true);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGBA8Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgRGBA8Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(TFPCompactImgRGBA8BitValue)*AWidth*AHeight);
+ inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGB8Bit }
+
+function TFPCompactImgRGB8Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+ v: TFPCompactImgRGB8BitValue;
+begin
+ v:=FData[x+y*Width];
+ Result.red:=(v.r shl 8)+v.r;
+ Result.green:=(v.g shl 8)+v.g;
+ Result.blue:=(v.b shl 8)+v.b;
+ Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgRGB8Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgRGB8Bit.SetInternalColor(x, y: integer; const Value: TFPColor
+ );
+var
+ v: TFPCompactImgRGB8BitValue;
+begin
+ v.r:=Value.red shr 8;
+ v.g:=Value.green shr 8;
+ v.b:=Value.blue shr 8;
+ FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgRGB8Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGB8Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(false,8,false);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGB8Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgRGB8Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(TFPCompactImgRGB8BitValue)*AWidth*AHeight);
+ inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGB16Bit }
+
+function TFPCompactImgRGB16Bit.GetInternalColor(x, y: integer): TFPColor;
+var
+ v: TFPCompactImgRGB16BitValue;
+begin
+ v:=FData[x+y*Width];
+ Result.red:=v.r;
+ Result.green:=v.g;
+ Result.blue:=v.b;
+ Result.alpha:=alphaOpaque;
+end;
+
+function TFPCompactImgRGB16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgRGB16Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+var
+ v: TFPCompactImgRGB16BitValue;
+begin
+ v.r:=Value.red;
+ v.g:=Value.green;
+ v.b:=Value.blue;
+ FData[x+y*Width]:=v;
+end;
+
+procedure TFPCompactImgRGB16Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGB16Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(false,16,false);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGB16Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgRGB16Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(TFPCompactImgRGB16BitValue)*AWidth*AHeight);
+ inherited SetSize(AWidth,AHeight);
+end;
+
+{ TFPCompactImgRGBA16Bit }
+
+function TFPCompactImgRGBA16Bit.GetInternalColor(x, y: integer): TFPColor;
+begin
+ Result:=FData[x+y*Width];
+end;
+
+function TFPCompactImgRGBA16Bit.GetInternalPixel(x, y: integer): integer;
+begin
+ Result:=0;
+end;
+
+procedure TFPCompactImgRGBA16Bit.SetInternalColor(x, y: integer;
+ const Value: TFPColor);
+begin
+ FData[x+y*Width]:=Value;
+end;
+
+procedure TFPCompactImgRGBA16Bit.SetInternalPixel(x, y: integer; Value: integer);
+begin
+
+end;
+
+constructor TFPCompactImgRGBA16Bit.Create(AWidth, AHeight: integer);
+begin
+ FDesc:=GetFPCompactImgDesc(false,16,true);
+ inherited Create(AWidth, AHeight);
+end;
+
+destructor TFPCompactImgRGBA16Bit.Destroy;
+begin
+ ReAllocMem(FData,0);
+ inherited Destroy;
+end;
+
+procedure TFPCompactImgRGBA16Bit.SetSize(AWidth, AHeight: integer);
+begin
+ if (AWidth=Width) and (AHeight=Height) then exit;
+ ReAllocMem(FData,SizeOf(TFPColor)*AWidth*AHeight);
+ inherited SetSize(AWidth,AHeight);
+end;
+
+
diff --git a/mips/packages/fcl-image/src/fpimage.pp b/mips/packages/fcl-image/src/fpimage.pp
index e98ebd7c19..fde1c6bf12 100644
--- a/mips/packages/fcl-image/src/fpimage.pp
+++ b/mips/packages/fcl-image/src/fpimage.pp
@@ -343,6 +343,202 @@ function CreateWebSafePalette : TFPPalette;
function CreateGrayScalePalette : TFPPalette;
function CreateVGAPalette : TFPPalette;
+Type
+ TFPCompactImgDesc = record
+ Gray: boolean; // true = red=green=blue, false: a RGB image
+ Depth: word; // 8 or 16 bit
+ HasAlpha: boolean; // has alpha channel
+ end;
+
+ { TFPCompactImgBase }
+
+ TFPCompactImgBase = class(TFPCustomImage)
+ private
+ FDesc: TFPCompactImgDesc;
+ public
+ property Desc: TFPCompactImgDesc read FDesc;
+ end;
+ TFPCompactImgBaseClass = class of TFPCompactImgBase;
+
+ { TFPCompactImgGray16Bit }
+
+ TFPCompactImgGray16Bit = class(TFPCompactImgBase)
+ protected
+ FData: PWord;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ TFPCompactImgGrayAlpha16BitValue = packed record
+ g,a: word;
+ end;
+ PFPCompactImgGrayAlpha16BitValue = ^TFPCompactImgGrayAlpha16BitValue;
+
+ { TFPCompactImgGrayAlpha16Bit }
+
+ TFPCompactImgGrayAlpha16Bit = class(TFPCompactImgBase)
+ protected
+ FData: PFPCompactImgGrayAlpha16BitValue;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ { TFPCompactImgGray8Bit }
+
+ TFPCompactImgGray8Bit = class(TFPCompactImgBase)
+ protected
+ FData: PByte;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ TFPCompactImgGrayAlpha8BitValue = packed record
+ g,a: byte;
+ end;
+ PFPCompactImgGrayAlpha8BitValue = ^TFPCompactImgGrayAlpha8BitValue;
+
+ { TFPCompactImgGrayAlpha8Bit }
+
+ TFPCompactImgGrayAlpha8Bit = class(TFPCompactImgBase)
+ protected
+ FData: PFPCompactImgGrayAlpha8BitValue;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ TFPCompactImgRGBA8BitValue = packed record
+ r,g,b,a: byte;
+ end;
+ PFPCompactImgRGBA8BitValue = ^TFPCompactImgRGBA8BitValue;
+
+ { TFPCompactImgRGBA8Bit }
+
+ TFPCompactImgRGBA8Bit = class(TFPCompactImgBase)
+ protected
+ FData: PFPCompactImgRGBA8BitValue;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ TFPCompactImgRGB8BitValue = packed record
+ r,g,b: byte;
+ end;
+ PFPCompactImgRGB8BitValue = ^TFPCompactImgRGB8BitValue;
+
+ { TFPCompactImgRGB8Bit }
+
+ TFPCompactImgRGB8Bit = class(TFPCompactImgBase)
+ protected
+ FData: PFPCompactImgRGB8BitValue;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ TFPCompactImgRGB16BitValue = packed record
+ r,g,b: word;
+ end;
+ PFPCompactImgRGB16BitValue = ^TFPCompactImgRGB16BitValue;
+
+ { TFPCompactImgRGB16Bit }
+
+ TFPCompactImgRGB16Bit = class(TFPCompactImgBase)
+ protected
+ FData: PFPCompactImgRGB16BitValue;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+ { TFPCompactImgRGBA16Bit }
+
+ TFPCompactImgRGBA16Bit = class(TFPCompactImgBase)
+ protected
+ FData: PFPColor;
+ function GetInternalColor(x, y: integer): TFPColor; override;
+ function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
+ procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
+ procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
+ public
+ constructor Create(AWidth, AHeight: integer); override;
+ destructor Destroy; override;
+ procedure SetSize(AWidth, AHeight: integer); override;
+ end;
+
+{ Create a descriptor to select a CompactImg class }
+function GetFPCompactImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean): TFPCompactImgDesc;
+
+{ Returns a CompactImg class that fits the descriptor }
+function GetFPCompactImgClass(const Desc: TFPCompactImgDesc): TFPCompactImgBaseClass;
+
+{ Create a CompactImg with the descriptor }
+function CreateFPCompactImg(const Desc: TFPCompactImgDesc; Width, Height: integer): TFPCustomImage;
+
+{ Create a CompactImg with the same features as Img.
+If Img is a TFPCompactImgBaseClass it will create that.
+Otherwise it returns a CompactImg that fits the Img using GetMinimumPTDesc. }
+function CreateCompatibleFPCompactImg(Img: TFPCustomImage; Width, Height: integer
+): TFPCustomImage;
+
+{ As CreateCompatibleFPCompactImg, but the image has always an alpha channel. }
+function CreateCompatibleFPCompactImgWithAlpha(Img: TFPCustomImage;
+Width, Height: integer): TFPCustomImage;
+
+{ Returns the smallest descriptor that allows to store the Img.
+It returns HasAlpha=false if all pixel are opaque.
+It returns Gray=true if all red=green=blue.
+It returns Depth=8 if all lo byte equals the hi byte or all lo bytes are 0.
+To ignore rounding errors you can pass a FuzzyDepth. For example a FuzzyDepth
+of 3 ignores the lower 3 bits when comparing. }
+function GetMinimumPTDesc(Img: TFPCustomImage; FuzzyDepth: word = 4): TFPCompactImgDesc;
+
+{ Create a smaller CompactImg with the same information as Img.
+Pass FreeImg=true to call Img.Free }
+function GetMinimumFPCompactImg(Img: TFPCustomImage; FreeImg: boolean;
+FuzzyDepth: word = 4): TFPCustomImage;
+
+
+
implementation
procedure FPImgError (Fmt:TErrorTextIndices; data : array of const);
@@ -359,6 +555,7 @@ end;
{$i FPHandler.inc}
{$i FPPalette.inc}
{$i FPColCnv.inc}
+{$i fpcompactimg.inc}
function FPColor (r,g,b:word) : TFPColor;
begin
diff --git a/mips/packages/fcl-image/src/fpimggauss.pp b/mips/packages/fcl-image/src/fpimggauss.pp
new file mode 100644
index 0000000000..3e070abed6
--- /dev/null
+++ b/mips/packages/fcl-image/src/fpimggauss.pp
@@ -0,0 +1,701 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2012 by the Free Pascal development team
+
+ fpImage Gaussian blur routines by Mattias Gaertner
+
+ 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 FPImgGauss;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Math, Classes, FPimage;
+
+{ Fast Gaussian blur to Area (excluding Area.Right and Area.Bottom)
+ Pixels outside the image are treated as having the same color as the edge.
+ This is a binominal approximation of fourth degree, so it is pretty near the
+ real gaussian blur in most cases but much faster for big radius.
+ Runtime: O((Area.Width+Radius) * (Area.Height+Radius)) }
+procedure GaussianBlurBinominal4(AImg: TFPCustomImage; Radius: integer;
+ SrcArea: TRect);
+procedure GaussianBlurBinominal4(SrcImg, DestImg: TFPCustomImage; Radius: integer;
+ SrcArea: TRect; DestXY: TPoint);
+
+{ Gaussian blur to Area (excluding Area.Right and Area.Bottom)
+ Pixels outside the image are treated as having the same color as the edge.
+ Runtime: O(Area.Width * Area.Height * Radius) }
+procedure GaussianBlur(Img: TFPCustomImage; Radius: integer; Area: TRect);
+
+{ MatrixBlur1D
+ The Matrix1D has a width of Radius*2+1.
+ The sum of all entries in the Matrix1D must be <= 65536.
+ Create Matrix1D with ComputeGaussianBlurMatrix1D.
+ Each pixel x,y in Area is replaced by a pixel computed from all pixels in
+ x-Radius..x+Radius, y-Radius..y+Radius
+ The new value is the sum of all pixels multiplied by Matrix1D, once
+ horizontally and once vertically.
+
+ Pixels outside the image are treated as having the same color as the edge.
+
+ Runtime is O(Area width * Area height * Radius) }
+procedure MatrixBlur1D(Img: TFPCustomImage; Radius: integer; Area: TRect; Matrix1D: PWord);
+
+{ MatrixBlur2D
+ The Matrix2D is quadratic and has a width of Radius*2+1.
+ The sum of all entries in the Matrix2D must be <= 65536.
+ Create Matrix2D with ComputeGaussianBlurMatrix2D.
+ Each pixel x,y in Area (Left..Right-1,Top..Bottom-1) is replaced by a pixel
+ computed from all pixels in x-Radius..x+Radius, y-Radius..y+Radius.
+ The new value is the sum of all pixels multiplied by Matrix2D.
+
+ Pixels outside the image are treated as having the same color as the edge.
+
+ Runtime is O(Area width * Area height * Radius * Radius) }
+procedure MatrixBlur2D(Img: TFPCustomImage; Radius: integer; Area: TRect; Matrix2D: PWord);
+
+{ ComputeGaussianBlurMatrix1D creates a one dimensional matrix of size
+ Width = Radius*2+1
+
+ Deviation := Radius / 3
+ G(x) := (1 / SQRT( 2 * pi * Deviation^2)) * e^( - (x^2) / (2 * Deviation^2) )
+
+ Each word is a factor [0,1) multiplied by 65536.
+ The total sum of the matrix is 65536. }
+function ComputeGaussianBlurMatrix1D(Radius: integer): PWord;
+
+{ ComputeGaussianBlurMatrix2D creates a two dimensional matrix of quadratic size
+ Width = Radius*2+1
+
+ Deviation := Radius / 3
+ G(x,y) := (1 / (2 * pi * Deviation^2)) * e^( - (x^2 + y^2) / (2 * Deviation^2) )
+
+ Each word is a factor [0,1) multiplied by 65536.
+ The total sum of the matrix is 65536. }
+function ComputeGaussianBlurMatrix2D(Radius: integer): PWord;
+
+implementation
+
+type
+
+ { TIntRingBuffer }
+
+ TIntRingBuffer = object
+ private
+ FSize: integer;
+ procedure SetSize(AValue: integer);
+ public
+ RingBuffer: PFPColor;
+ procedure Put(Index: integer; const Col: TFPColor);
+ procedure Get(Index: integer; out Col: TFPColor);
+ property Size: integer read FSize write SetSize;
+ procedure Init(len: integer);
+ procedure Clear;
+ end;
+
+{ TIntRingBuffer }
+
+procedure TIntRingBuffer.SetSize(AValue: integer);
+begin
+ if FSize=AValue then Exit;
+ FSize:=AValue;
+ ReAllocMem(RingBuffer,AValue*SizeOf(TFPColor));
+end;
+
+procedure TIntRingBuffer.Put(Index: integer; const Col: TFPColor);
+begin
+ Index:=Index mod FSize;
+ if Index<0 then inc(Index,FSize);
+ RingBuffer[Index]:=Col;
+end;
+
+procedure TIntRingBuffer.Get(Index: integer; out Col: TFPColor);
+begin
+ Index:=Index mod FSize;
+ if Index<0 then inc(Index,FSize);
+ Col:=RingBuffer[Index];
+end;
+
+procedure TIntRingBuffer.Init(len: integer);
+begin
+ FSize:=0;
+ RingBuffer:=nil;
+ Size:=len;
+end;
+
+procedure TIntRingBuffer.Clear;
+begin
+ Size:=0;
+end;
+
+procedure GaussianBlurBinominal4(AImg: TFPCustomImage; Radius: integer;
+ SrcArea: TRect);
+begin
+ GaussianBlurBinominal4(AImg,AImg,Radius,SrcArea,SrcArea.TopLeft);
+end;
+
+procedure GaussianBlurBinominal4(SrcImg, DestImg: TFPCustomImage;
+ Radius: integer; SrcArea: TRect; DestXY: TPoint);
+type
+ TIntegerColor = record
+ red, green, blue, alpha: integer;
+ end;
+const
+ clearIntegerColor: TIntegerColor = (red:0;green:0;blue:0;alpha:0);
+var
+ x,y,i: LongInt;
+ Pixel: TFPColor;
+ difference: TIntegerColor;
+ derivative1: TIntegerColor;
+ derivative2: TIntegerColor;
+ sum: TIntegerColor;
+ Weight: Single;
+ col: TFPColor;
+ buffer: TIntRingBuffer;
+ Col1, Col2, Col3, Col4: TFPColor;
+begin
+ // clip
+ if SrcArea.Left<0 then begin
+ dec(DestXY.X,SrcArea.Left);
+ SrcArea.Left:=0;
+ end;
+ if SrcArea.Top<0 then begin
+ dec(DestXY.Y,SrcArea.Top);
+ SrcArea.Top:=0;
+ end;
+ SrcArea.Right:=Min(SrcImg.Width,SrcArea.Right);
+ SrcArea.Top:=Min(SrcImg.Height,SrcArea.Top);
+ SrcArea.Right:=Min(SrcArea.Right,DestImg.Width-DestXY.X+SrcArea.Left);
+ SrcArea.Bottom:=Min(SrcArea.Bottom,DestImg.Height-DestXY.Y+SrcArea.Top);
+ if SrcArea.Left>=SrcArea.Right then exit;
+ if SrcArea.Top>=SrcArea.Bottom then exit;
+
+ // blur -- RingBuffer of Size 147 is needed. range=(0,(int)(N_CELLS/4/1.73))
+ // N_CELLS=1024 don't ask! see paper: gauss.pdf, 3.sourcecdoe
+ // Or 4*Radius+1, sounds better. see Comment underneath
+ //Radius:=round(sqrt(3*Radius*Radius));
+ buffer.Init(4*Radius);
+ Weight := 1.0/(single(Radius*Radius*Radius*Radius));
+ // vertical blur
+ for x:=SrcArea.Left to SrcArea.Right-1 do begin
+ // set up init values for the first blur
+ difference:=clearIntegerColor;
+ derivative1:=clearIntegerColor;
+ derivative2:=clearIntegerColor;
+ sum:=clearIntegerColor;
+ for y:=SrcArea.Top-4*Radius to SrcArea.Bottom-1 do begin
+ if y >= SrcArea.Top then begin //{+1,-4,+6,-4,+1}
+ buffer.Get(y-2*Radius,Col1);
+ buffer.Get(y-Radius,Col2);
+ buffer.Get(y,Col3);
+ buffer.Get(y+Radius,Col4);
+ difference.alpha :=difference.alpha+Col1.alpha-4*(Col2.alpha+Col4.alpha)+6*Col3.alpha;
+ difference.red :=difference.red +Col1.red -4*(Col2.red +Col4.red) +6*Col3.red;
+ difference.green :=difference.green+Col1.green-4*(Col2.green+Col4.green)+6*Col3.green;
+ difference.blue :=difference.blue +Col1.blue -4*(Col2.blue +Col4.blue) +6*Col3.blue;
+ col:=SrcImg.Colors[x,y];
+ col.alpha:=min($FFFF,max(0,round(sum.alpha*Weight)));
+ col.red :=min($FFFF,max(0,round(sum.red *Weight)));
+ col.green:=min($FFFF,max(0,round(sum.green*Weight)));
+ col.blue :=min($FFFF,max(0,round(sum.blue *Weight)));
+ DestImg.Colors[x,y]:=col; // set blurred pixel
+ end else begin
+ if (y+3*Radius) >= SrcArea.Top then begin
+ // -4*buffer(y+Radius)
+ buffer.Get(y+Radius,Col4);
+ difference.alpha:=difference.alpha-4*Col4.alpha;
+ difference.red :=difference.red -4*Col4.red;
+ difference.green:=difference.green-4*Col4.green;
+ difference.blue :=difference.blue -4*Col4.blue;
+ end;
+ if (y+2*Radius) >= SrcArea.Top then begin
+ // +6*buffer(y)
+ buffer.Get(y,Col3);
+ difference.alpha:=difference.alpha+6*Col4.alpha;
+ difference.red :=difference.red +6*Col4.red;
+ difference.green:=difference.green+6*Col4.green;
+ difference.blue :=difference.blue +6*Col4.blue;
+ end;
+ if (y+ Radius) >= SrcArea.Top then begin
+ // -4*buffer(y-Radius)
+ buffer.Get(y-Radius,Col2);
+ difference.alpha:=difference.alpha-4*Col2.alpha;
+ difference.red :=difference.red -4*Col2.red;
+ difference.green:=difference.green-4*Col2.green;
+ difference.blue :=difference.blue -4*Col2.blue;
+ end;
+ end;
+ i:=Min(DestImg.Height-1,Max(0,y+2*Radius-1));
+ // accumulate pixel blur
+ pixel := SrcImg.Colors[x,i];
+ difference.alpha := difference.alpha+pixel.alpha;
+ difference.red := difference.red +pixel.red;
+ difference.green := difference.green+pixel.green;
+ difference.blue := difference.blue +pixel.blue;
+ derivative2.alpha := derivative2.alpha+difference.alpha;
+ derivative2.red := derivative2.red +difference.red;
+ derivative2.green := derivative2.green+difference.green;
+ derivative2.blue := derivative2.blue +difference.blue;
+ derivative1.alpha := derivative1.alpha+derivative2.alpha;
+ derivative1.red := derivative1.red +derivative2.red;
+ derivative1.green := derivative1.green+derivative2.green;
+ derivative1.blue := derivative1.blue +derivative2.blue;
+ sum.alpha := sum.alpha+derivative1.alpha;
+ sum.red := sum.red +derivative1.red;
+ sum.green := sum.green+derivative1.green;
+ sum.blue := sum.blue +derivative1.blue;
+ buffer.Put(y+2*Radius,pixel); // buffer pixel, min buffer size: 4*Radius
+ end;
+ end;
+
+ //horizontal blur
+ for y:=SrcArea.Top to SrcArea.Bottom-1 do begin
+ // set up init values for the first blur
+ difference:=clearIntegerColor;
+ derivative1:=clearIntegerColor;
+ derivative2:=clearIntegerColor;
+ sum:=clearIntegerColor;
+ for x:=SrcArea.Left-4*Radius to SrcArea.Right-1 do begin
+ if x >= SrcArea.Left then begin //{+1,-4,+6,-4,+1}
+ buffer.Get(x-2*Radius,Col1);
+ buffer.Get(x-Radius,Col2);
+ buffer.Get(x,Col3);
+ buffer.Get(x+Radius,Col4);
+ difference.alpha :=difference.alpha+Col1.alpha-4*(Col2.alpha+Col4.alpha)+6*Col3.alpha;
+ difference.red :=difference.red +Col1.red -4*(Col2.red +Col4.red) +6*Col3.red;
+ difference.green :=difference.green+Col1.green-4*(Col2.green+Col4.green)+6*Col3.green;
+ difference.blue :=difference.blue +Col1.blue -4*(Col2.blue +Col4.blue) +6*Col3.blue;
+ col:=DestImg.Colors[x,y];
+ col.alpha:=min($FFFF,max(0,round(sum.alpha*Weight)));
+ col.red :=min($FFFF,max(0,round(sum.red *Weight)));
+ col.green:=min($FFFF,max(0,round(sum.green*Weight)));
+ col.blue :=min($FFFF,max(0,round(sum.blue *Weight)));
+ DestImg.Colors[x,y]:=col; // set blurred pixel
+ end else begin
+ if (x+3*Radius) >= SrcArea.Left then begin
+ // -4*buffer(x+Radius)
+ buffer.Get(x+Radius,Col4);
+ difference.alpha:=difference.alpha-4*Col4.alpha;
+ difference.red :=difference.red -4*Col4.red;
+ difference.green:=difference.green-4*Col4.green;
+ difference.blue :=difference.blue -4*Col4.blue;
+ end;
+ if (x+2*Radius) >= SrcArea.Left then begin
+ // +6*buffer(x)
+ buffer.Get(x,Col3);
+ difference.alpha:=difference.alpha+6*Col3.alpha;
+ difference.red :=difference.red +6*Col3.red;
+ difference.green:=difference.green+6*Col3.green;
+ difference.blue :=difference.blue +6*Col3.blue;
+ end;
+ if (x+ Radius) >= SrcArea.Left then begin
+ // -4*buffer(x-Radius)
+ buffer.Get(x-Radius,Col2);
+ difference.alpha:=difference.alpha-4*Col2.alpha;
+ difference.red :=difference.red -4*Col2.red;
+ difference.green:=difference.green-4*Col2.green;
+ difference.blue :=difference.blue -4*Col2.blue;
+ end;
+ end;
+ i:=Min(DestImg.Width-1,Max(0,x+2*Radius-1));
+ // accumulate pixel blur
+ pixel := DestImg.Colors[i,y];
+ difference.alpha := difference.alpha+pixel.alpha;
+ difference.red := difference.red +pixel.red;
+ difference.green := difference.green+pixel.green;
+ difference.blue := difference.blue +pixel.blue;
+ derivative2.alpha := derivative2.alpha+difference.alpha;
+ derivative2.red := derivative2.red +difference.red;
+ derivative2.green := derivative2.green+difference.green;
+ derivative2.blue := derivative2.blue +difference.blue;
+ derivative1.alpha := derivative1.alpha+derivative2.alpha;
+ derivative1.red := derivative1.red +derivative2.red;
+ derivative1.green := derivative1.green+derivative2.green;
+ derivative1.blue := derivative1.blue +derivative2.blue;
+ sum.alpha := sum.alpha+derivative1.alpha;
+ sum.red := sum.red +derivative1.red;
+ sum.green := sum.green+derivative1.green;
+ sum.blue := sum.blue +derivative1.blue;
+
+ buffer.Put(x+2*Radius,pixel); // buffer pixel, min buffer size: 4*Radius
+ end;
+ end;
+ buffer.Clear;
+end;
+
+procedure GaussianBlur(Img: TFPCustomImage; Radius: integer; Area: TRect);
+var
+ Matrix: PWord;
+begin
+ // check input
+ if (Radius<1) then exit;
+ Area.Left:=Max(0,Area.Left);
+ Area.Top:=Max(0,Area.Top);
+ Area.Right:=Min(Area.Right,Img.Width);
+ Area.Bottom:=Min(Area.Bottom,Img.Height);
+ if (Area.Left>=Area.Right) or (Area.Top>=Area.Bottom) then exit;
+
+ // compute gaussian matrix
+ Matrix:=ComputeGaussianBlurMatrix1D(Radius);
+ try
+ MatrixBlur1D(Img,Radius,Area,Matrix);
+ finally
+ FreeMem(Matrix);
+ end;
+end;
+
+procedure MatrixBlur1D(Img: TFPCustomImage; Radius: integer; Area: TRect;
+ Matrix1D: PWord);
+{ Implementation:
+ It runs line by line from Area.Left to Area.Bottom-1.
+ It allocates some temporary memory to store the original pixel values
+ above the current line.
+}
+var
+ y: Integer;
+ x: Integer;
+ OrigWidth: Integer;
+ OrigHeight: LongInt;
+ OrigPixels: PFPColor;
+ VertSums: PFPColor;
+ NewRed, NewGreen, NewBlue, NewAlpha: cardinal;
+ yd: LongInt;
+ xd: LongInt;
+ xr: Integer;
+ yr: Integer;
+ Col: TFPColor;
+ NewCol: TFPColor;
+ Multiplier: Word;
+ StartX: Integer;
+ EndX: Integer;
+begin
+ // check input
+ if (Radius<1) then exit;
+ Area.Left:=Max(0,Area.Left);
+ Area.Top:=Max(0,Area.Top);
+ Area.Right:=Min(Area.Right,Img.Width);
+ Area.Bottom:=Min(Area.Bottom,Img.Height);
+ if (Area.Left>=Area.Right) or (Area.Top>=Area.Bottom) then exit;
+
+ //for x:=0 to MatrixWidth-1 do WriteLn('GaussianBlurNew ',x,' ',Matrix[x]);
+ OrigPixels:=nil;
+ VertSums:=nil;
+ try
+ // allocate space for original pixels
+ OrigWidth:=Area.Right-Area.Left;
+ OrigHeight:=Radius+1;
+ //writeln('GaussianBlur ',OrigWidth,'*',OrigHeight,'*',SizeOf(TFPColor));
+ GetMem(OrigPixels,OrigWidth*OrigHeight*SizeOf(TFPColor));
+ // get original pixels (the bottom line of OrigPixels will be Area.Top)
+ y:=Area.Top;
+ for yd:=-Radius to 0 do begin
+ yr:=Max(0,y+yd);
+ for x:=Area.Left to Area.Right-1 do begin
+ OrigPixels[x-Area.Left+(yd+Radius)*OrigWidth]:=Img.Colors[x,yr];
+ end;
+ end;
+
+ GetMem(VertSums,(OrigWidth+2*Radius)*SizeOf(TFPColor));
+
+ // compute new pixels
+ for y:=Area.Top to Area.Bottom-1 do begin
+ // move OrigPixels one line up
+ System.Move(OrigPixels[OrigWidth],OrigPixels[0],
+ OrigWidth*(OrigHeight-1)*SizeOf(TFPColor));
+ // and copy current line to OrigPixels
+ for x:=Area.Left to Area.Right-1 do begin
+ OrigPixels[x-Area.Left+Radius*OrigWidth]:=Img.Colors[x,y];
+ end;
+
+ // compute vertical sums
+ // (for each x compute the sum of y-Radius..y+Radius colors
+ // multiplied with the gaussian matrix)
+ StartX:=Area.Left-Radius;
+ EndX:=Area.Right-1+Radius;
+ for x:=StartX to EndX do begin
+ // xr: x coordinate on img (coords out of bounds are mapped to the edges)
+ xr:=Min(Max(0,x),Img.Width-1);
+ // compute new color for this pixel
+ NewRed:=0;
+ NewGreen:=0;
+ NewBlue:=0;
+ NewAlpha:=0;
+ for yd:=-Radius to Radius do begin
+ // yr: y coordinate on img (coords out of bounds are mapped to the edges)
+ yr:=Min(Max(0,y+yd),Img.Height-1);
+ // get color
+ if (yd<=0) and (xr>=Area.Left) and (xr<Area.Right) then begin
+ // this pixel was replaced => use the OrigPixels
+ Col:=OrigPixels[xr-Area.Left+(yd+Radius)*OrigWidth];
+ end else begin
+ Col:=Img.Colors[xr,yr];
+ end;
+ // multiply with gaussian matrix
+ Multiplier:=Matrix1D[yd+Radius];
+ inc(NewRed,Col.red*Multiplier);
+ inc(NewGreen,Col.green*Multiplier);
+ inc(NewBlue,Col.blue*Multiplier);
+ inc(NewAlpha,Col.alpha*Multiplier);
+ //writeln('GaussianBlur x=',x,' y=',y,' xd=',xd,' yd=',yd,' xr=',xr,' yr=',yr,' Col=',dbgs(Col),' NewCol=r=',hexstr(NewRed,8),'g=',hexstr(NewGreen,8),'b=',hexstr(NewBlue,8),'a=',hexstr(NewAlpha,8));
+ end;
+ NewCol.red:=NewRed shr 16;
+ NewCol.green:=NewGreen shr 16;
+ NewCol.blue:=NewBlue shr 16;
+ NewCol.alpha:=NewAlpha shr 16;
+ VertSums[x-StartX]:=NewCol;
+ end;
+
+ // compute horizontal sums
+ // (for each x compute the sum of x-Radius..x+Radius vertical sums
+ // multiplied with the gaussian matrix)
+ for x:=Area.Left to Area.Right-1 do begin
+ // compute new color for this pixel
+ NewRed:=0;
+ NewGreen:=0;
+ NewBlue:=0;
+ NewAlpha:=0;
+ for xd:=-Radius to Radius do begin
+ xr:=x+xd;
+ Col:=VertSums[xr-StartX];
+ // multiply with gaussian matrix
+ Multiplier:=Matrix1D[xd+Radius];
+ inc(NewRed,Col.red*Multiplier);
+ inc(NewGreen,Col.green*Multiplier);
+ inc(NewBlue,Col.blue*Multiplier);
+ inc(NewAlpha,Col.alpha*Multiplier);
+ //writeln('GaussianBlur x=',x,' y=',y,' xd=',xd,' yd=',yd,' xr=',xr,' yr=',yr,' Col=',dbgs(Col),' NewCol=r=',hexstr(NewRed,8),'g=',hexstr(NewGreen,8),'b=',hexstr(NewBlue,8),'a=',hexstr(NewAlpha,8));
+ end;
+ NewCol.red:=NewRed shr 16;
+ NewCol.green:=NewGreen shr 16;
+ NewCol.blue:=NewBlue shr 16;
+ NewCol.alpha:=NewAlpha shr 16;
+ // set new pixel
+ //writeln('GaussianBlur x=',x,' y=',y,' OldCol=',dbgs(img.Colors[x,y]),' NewCol=',dbgs(NewCol));
+ Img.Colors[x,y]:=NewCol;
+ end;
+ end;
+ finally
+ if OrigPixels<>nil then FreeMem(OrigPixels);
+ if VertSums<>nil then FreeMem(VertSums);
+ end;
+end;
+
+procedure MatrixBlur2D(Img: TFPCustomImage; Radius: integer; Area: TRect;
+ Matrix2D: PWord);
+{ Implementation:
+ It runs line by line from Area.Left to Area.Bottom-1.
+ It allocates some temporary memory to store the original pixel values
+ above the current line.
+}
+var
+ y: Integer;
+ x: Integer;
+ OrigWidth: Integer;
+ OrigHeight: LongInt;
+ OrigPixels: PFPColor;
+ NewRed, NewGreen, NewBlue, NewAlpha: cardinal;
+ yd: LongInt;
+ xd: LongInt;
+ xr: Integer;
+ yr: Integer;
+ Col: TFPColor;
+ NewCol: TFPColor;
+ Multiplier: Word;
+ MatrixWidth: Integer;
+begin
+ // check input
+ if (Radius<1) then exit;
+ Area.Left:=Max(0,Area.Left);
+ Area.Top:=Max(0,Area.Top);
+ Area.Right:=Min(Area.Right,Img.Width);
+ Area.Bottom:=Min(Area.Bottom,Img.Height);
+ if (Area.Left>=Area.Right) or (Area.Top>=Area.Bottom) then exit;
+
+ MatrixWidth:=Radius*2+1;
+ //WriteM('matrix ',Matrix2D,MatrixWidth);
+ OrigPixels:=nil;
+ try
+ // allocate space for original pixels
+ OrigWidth:=Area.Right-Area.Left;
+ OrigHeight:=Radius+1;
+ //DebugLn(['GaussianBlur ',OrigWidth,'*',OrigHeight,'*',SizeOf(TFPColor)]);
+ GetMem(OrigPixels,OrigWidth*OrigHeight*SizeOf(TFPColor));
+ // get original pixels (the bottom line of OrigPixels will be Area.Top)
+ y:=Area.Top;
+ for yd:=-Radius to 0 do begin
+ yr:=Max(0,y+yd);
+ for x:=Area.Left to Area.Right-1 do begin
+ OrigPixels[x-Area.Left+(yd+Radius)*OrigWidth]:=Img.Colors[x,yr];
+ end;
+ end;
+
+ // compute new pixels
+ for y:=Area.Top to Area.Bottom-1 do begin
+ // move OrigPixels one line up
+ System.Move(OrigPixels[OrigWidth],OrigPixels[0],
+ OrigWidth*(OrigHeight-1)*SizeOf(TFPColor));
+ // and copy current line to OrigPixels
+ for x:=Area.Left to Area.Right-1 do begin
+ OrigPixels[x-Area.Left+Radius*OrigWidth]:=Img.Colors[x,y];
+ end;
+ // compute line
+ for x:=Area.Left to Area.Right-1 do begin
+ // compute new color for this pixel
+ NewRed:=0;
+ NewGreen:=0;
+ NewBlue:=0;
+ NewAlpha:=0;
+ for yd:=-Radius to Radius do begin
+ // yr: y coordinate on img (coords out of bounds are mapped to the edges)
+ yr:=Min(Max(0,y+yd),Img.Height-1);
+ for xd:=-Radius to Radius do begin
+ // xr: x coordinate on img (coords out of bounds are mapped to the edges)
+ xr:=Min(Max(0,x+xd),Img.Width-1);
+ // get color
+ if (yd<=0) and (xr>=Area.Left) and (xr<Area.Right) then begin
+ // this pixel was replaced => use the OrigPixels
+ Col:=OrigPixels[xr-Area.Left+(yd+Radius)*OrigWidth];
+ end else begin
+ Col:=Img.Colors[xr,yr];
+ end;
+ // multiply with gauss Matrix2D
+ Multiplier:=Matrix2D[xd+Radius+(yd+Radius)*MatrixWidth];
+ inc(NewRed,Col.red*Multiplier);
+ inc(NewGreen,Col.green*Multiplier);
+ inc(NewBlue,Col.blue*Multiplier);
+ inc(NewAlpha,Col.alpha*Multiplier);
+ //DebugLn(['GaussianBlur x=',x,' y=',y,' xd=',xd,' yd=',yd,' xr=',xr,' yr=',yr,' Col=',dbgs(Col),' NewCol=r=',hexstr(NewRed,8),'g=',hexstr(NewGreen,8),'b=',hexstr(NewBlue,8),'a=',hexstr(NewAlpha,8)]);
+ end;
+ end;
+ NewCol.red:=NewRed shr 16;
+ NewCol.green:=NewGreen shr 16;
+ NewCol.blue:=NewBlue shr 16;
+ NewCol.alpha:=NewAlpha shr 16;
+ // set new pixel
+ //DebugLn(['GaussianBlur x=',x,' y=',y,' OldCol=',dbgs(img.Colors[x,y]),' NewCol=',dbgs(NewCol)]);
+ Img.Colors[x,y]:=NewCol;
+ end;
+ end;
+ finally
+ if OrigPixels<>nil then FreeMem(OrigPixels);
+ end;
+end;
+
+function ComputeGaussianBlurMatrix1D(Radius: integer): PWord;
+// returns a 1dim matrix of Words for the gaussian blur.
+// Each word is a factor [0,1) multiplied by 65536.
+// The total sum of the matrix is 65536.
+const
+ StandardDeviationToRadius = 3; // Pixels more far away as 3*Deviation are too small
+var
+ Width: Integer;
+ Size: Integer;
+ Matrix: PWord;
+ Deviation: Single;
+ m,p: Single;
+ x: Integer;
+ Value: Integer;
+ MatrixSum: Integer;
+ g: Single;
+begin
+ Width:=Radius*2+1;
+ Size:=SizeOf(Word)*Width*Width;
+ Matrix:=nil;
+ GetMem(Matrix,Size);
+ Result:=Matrix;
+ FillByte(Matrix^,Size,0);
+ // Deviation := Radius / 3
+ // G(x) := (1 / SQRT( 2 * pi * Deviation^2)) * e^( - (x^2) / (2 * Deviation^2) )
+ // m * e^( x^2 * p )
+ // m := 1 / SQRT( 2 * pi * Deviation^2)
+ // p := -1 / (2 * Deviation^2)
+ Deviation:=single(Radius)/StandardDeviationToRadius;
+ m:=1/Sqrt(2*pi*Deviation*Deviation);
+ p:=-1/(2*Deviation*Deviation);
+ for x:=0 to Radius do begin
+ g:=m*exp(single(x*x)*p);
+ Value:=floor(g*65536);
+ Matrix[Radius+x]:=Value;
+ Matrix[Radius-x]:=Value;
+ end;
+ // fix sum to 65536
+ MatrixSum:=0;
+ for x:=0 to Width-1 do
+ inc(MatrixSum,Matrix[x]);
+ Matrix[Radius]:=Min(High(Word),65536-MatrixSum+Matrix[Radius]);
+end;
+
+function ComputeGaussianBlurMatrix2D(Radius: integer): PWord;
+// returns a 2dim matrix of Words for the gaussian blur.
+// Each word is a factor [0,1) multiplied by 65536.
+// The total sum of the matrix is 65536.
+const
+ StandardDeviationToRadius = 3; // Pixels more far away as 3*Deviation are too small
+var
+ Matrix: PWord;
+ Size: Integer;
+ Deviation: single;
+ m,p: single;
+ g: single;
+ y: Integer;
+ x: Integer;
+ yd: Integer;
+ xd: Integer;
+ MatrixSum: Integer;
+ Value: Word;
+ Width: Integer;
+begin
+ Width:=Radius*2+1;
+ Size:=SizeOf(Word)*Width*Width;
+ Matrix:=nil;
+ GetMem(Matrix,Size);
+ Result:=Matrix;
+ FillByte(Matrix^,Size,0);
+ // Deviation = Radius / StandardDeviationToRadius
+ // G(x,y) := (1 / (2 * pi * Deviation^2)) * e^( - (x^2 + y^2) / (2 * Deviation^2) )
+ // = m * e^( (x^2 + y^2) * p )
+ // m := 1 / (2 * pi * Deviation^2)
+ // p := -1 / (2 * Deviation^2)
+ Deviation:=single(Radius)/StandardDeviationToRadius;
+ m:=1/(2*pi*Deviation*Deviation);
+ p:=-1/(2*Deviation*Deviation);
+ for y:=0 to Radius do begin
+ yd:=Radius-y;
+ yd:=yd*yd;
+ for x:=y to Radius do begin
+ xd:=Radius-x;
+ xd:=xd*xd;
+ g:=m*exp((single(xd)+single(yd))*p);
+ Value:=floor(g*65536);
+ Matrix[x+y*Width]:=Value;
+ // mirror diagonally
+ Matrix[y+x*Width]:=Value;
+ end;
+ // mirror horizontally
+ for x:=Radius+1 to Width-1 do
+ Matrix[x+y*Width]:=Matrix[(Width-x-1)+y*Width];
+ // mirror vertically
+ System.Move(Matrix[y*Width],Matrix[(Width-y-1)*Width],SizeOf(Word)*Width);
+ end;
+ // fix sum to 65536
+ MatrixSum:=0;
+ for y:=0 to Width-1 do
+ for x:=0 to Width-1 do
+ inc(MatrixSum,Matrix[x+y*Width]);
+ Matrix[Radius+Radius*Width]:=Min(High(Word),65536-MatrixSum+Matrix[Radius+Radius*Width]);
+end;
+
+end.
+
diff --git a/mips/packages/fcl-image/src/fpinterpolation.inc b/mips/packages/fcl-image/src/fpinterpolation.inc
index 5fbef42ab8..7d2e594f38 100644
--- a/mips/packages/fcl-image/src/fpinterpolation.inc
+++ b/mips/packages/fcl-image/src/fpinterpolation.inc
@@ -179,7 +179,7 @@ begin
begin
sx:=PInteger(xEntry)^;
inc(xEntry,SizeOf(integer));
- NewCol:=colBlack;
+ NewCol:= colTransparent;
for cx:=0 to xSupport-1 do
begin
f:=PSingle(xEntry)^;
@@ -198,7 +198,7 @@ begin
for dx:=0 to w-1 do
begin
CurEntry:=yEntry+SizeOf(integer);
- NewCol:=colBlack;
+ NewCol:=colTransparent;
for sy:=0 to ySupport-1 do
begin
f:=PSingle(CurEntry)^;
diff --git a/mips/packages/fcl-image/src/fpwritepng.pp b/mips/packages/fcl-image/src/fpwritepng.pp
index 022e5a6dc9..32c23daeed 100644
--- a/mips/packages/fcl-image/src/fpwritepng.pp
+++ b/mips/packages/fcl-image/src/fpwritepng.pp
@@ -449,6 +449,7 @@ begin
// signature for PNG
TheStream.writeBuffer(Signature,sizeof(Signature));
// Determine all settings for filling the header
+ fillchar(fheader,sizeof(fheader),#0);
DetermineHeader (FHeader);
// write the header chunk
SetChunkLength (13); // (sizeof(FHeader)); gives 14 and is wrong !!
diff --git a/mips/packages/fcl-json/src/fpjson.pp b/mips/packages/fcl-json/src/fpjson.pp
index a1a771c1d0..99022cea54 100644
--- a/mips/packages/fcl-json/src/fpjson.pp
+++ b/mips/packages/fcl-json/src/fpjson.pp
@@ -396,6 +396,7 @@ Type
Function IndexOfName(const AName: TJSONStringType; CaseInsensitive : Boolean = False): Integer;
Function Find(Const AName : String) : TJSONData; overload;
Function Find(Const AName : String; AType : TJSONType) : TJSONData; overload;
+ Function Get(Const AName : String) : Variant;
Function Get(Const AName : String; ADefault : TJSONFloat) : TJSONFloat;
Function Get(Const AName : String; ADefault : Integer) : Integer;
Function Get(Const AName : String; ADefault : Int64) : Int64;
@@ -2059,6 +2060,18 @@ begin
Result:=Nil
end;
+function TJSONObject.Get(const AName: String): Variant;
+Var
+ I : Integer;
+
+begin
+ I:=IndexOfName(AName);
+ If (I<>-1) then
+ Result:=Items[i].Value
+ else
+ Result:=Null;
+end;
+
function TJSONObject.Get(const AName: String; ADefault: TJSONFloat
): TJSONFloat;
@@ -2158,7 +2171,7 @@ Var
begin
I:=IndexOfName(AName);
- If (I=-1) then
+ If (I<>-1) then
Result:=Items[i]
else
Result:=Nil;
diff --git a/mips/packages/fcl-json/src/fpjsonrtti.pp b/mips/packages/fcl-json/src/fpjsonrtti.pp
index 15f0c46b8c..239183b16d 100644
--- a/mips/packages/fcl-json/src/fpjsonrtti.pp
+++ b/mips/packages/fcl-json/src/fpjsonrtti.pp
@@ -20,8 +20,9 @@ Type
jsoComponentsInline, // Always stream components inline. Default is to stream name, unless csSubcomponent in ComponentStyle
jsoTStringsAsArray, // Stream TStrings as an array of strings. Associated objects are not streamed.
jsoTStringsAsObject, // Stream TStrings as an object : string = { object }
- jsoDateTimeAsString,
- jsoUseFormatString); // Use FormatString when creating JSON strings.
+ jsoDateTimeAsString, // Format a TDateTime value as a string
+ jsoUseFormatString, // Use FormatString when creating JSON strings.
+ jsoCheckEmptyDateTime); // If TDateTime value is empty and jsoDateTimeAsString is used, 0 date returns empty string
TJSONStreamOptions = Set of TJSONStreamOption;
TJSONFiler = Class(TComponent)
@@ -999,7 +1000,9 @@ Var
S: String;
begin
- if (DateTimeFormat<>'') then
+ if (jsoCheckEmptyDateTime in Options) and (DateTime=0) then
+ S:=''
+ else if (DateTimeFormat<>'') then
S:=FormatDateTime(DateTimeFormat,DateTime)
else if Frac(DateTime)=0 then
S:=DateToStr(DateTime)
diff --git a/mips/packages/fcl-json/src/jsonparser.pp b/mips/packages/fcl-json/src/jsonparser.pp
index 22726a79ad..2f03a92f0c 100644
--- a/mips/packages/fcl-json/src/jsonparser.pp
+++ b/mips/packages/fcl-json/src/jsonparser.pp
@@ -28,9 +28,12 @@ Type
TJSONParser = Class(TObject)
Private
FScanner : TJSONScanner;
+ FuseUTF8,
FStrict: Boolean;
function ParseNumber: TJSONNumber;
procedure SetStrict(const AValue: Boolean);
+ function GetUTF8 : Boolean;
+ procedure SetUTF8(const AValue: Boolean);
Protected
procedure DoError(const Msg: String);
function DoParse(AtCurrent,AllowEOF: Boolean): TJSONData;
@@ -42,11 +45,13 @@ Type
Property Scanner : TJSONScanner read FScanner;
Public
function Parse: TJSONData;
- Constructor Create(Source : TStream); overload;
- Constructor Create(Source : TJSONStringType); overload;
+ Constructor Create(Source : TStream; AUseUTF8 : Boolean = True); overload;
+ Constructor Create(Source : TJSONStringType; AUseUTF8 : Boolean = True); overload;
destructor Destroy();override;
// Use strict JSON: " for strings, object members are strings, not identifiers
Property Strict : Boolean Read FStrict Write SetStrict;
+ // if set to TRUE, then strings will be converted to UTF8 ansistrings, not system codepage ansistrings.
+ Property UseUTF8 : Boolean Read GetUTF8 Write SetUTF8;
end;
EJSONParser = Class(EParserError);
@@ -152,6 +157,23 @@ begin
end;
end;
+function TJSONParser.GetUTF8 : Boolean;
+
+begin
+ if Assigned(FScanner) then
+ Result:=FScanner.UseUTF8
+ else
+ Result:=FUseUTF8;
+end;
+
+procedure TJSONParser.SetUTF8(const AValue: Boolean);
+
+begin
+ FUseUTF8:=AValue;
+ if Assigned(FScanner) then
+ FScanner.UseUTF8:=FUseUTF8;
+end;
+
procedure TJSONParser.SetStrict(const AValue: Boolean);
begin
if (FStrict=AValue) then
@@ -250,16 +272,18 @@ begin
Raise EJSONParser.Create(S);
end;
-constructor TJSONParser.Create(Source: TStream);
+constructor TJSONParser.Create(Source: TStream; AUseUTF8 : Boolean = True);
begin
Inherited Create;
FScanner:=TJSONScanner.Create(Source);
+ UseUTF8:=AUseUTF8;
end;
-constructor TJSONParser.Create(Source: TJSONStringType);
+constructor TJSONParser.Create(Source: TJSONStringType; AUseUTF8 : Boolean = True);
begin
Inherited Create;
FScanner:=TJSONScanner.Create(Source);
+ UseUTF8:=AUseUTF8;
end;
destructor TJSONParser.Destroy();
diff --git a/mips/packages/fcl-json/src/jsonscanner.pp b/mips/packages/fcl-json/src/jsonscanner.pp
index 290307f576..e02a5d7437 100644
--- a/mips/packages/fcl-json/src/jsonscanner.pp
+++ b/mips/packages/fcl-json/src/jsonscanner.pp
@@ -59,6 +59,7 @@ type
FCurTokenString: string;
FCurLine: string;
FStrict: Boolean;
+ FUseUTF8 : Boolean;
TokenStr: PChar;
function GetCurColumn: Integer;
protected
@@ -66,8 +67,8 @@ type
procedure Error(const Msg: string; Args: array of Const);overload;
function DoFetchToken: TJSONToken;
public
- constructor Create(Source : TStream); overload;
- constructor Create(const Source : String); overload;
+ constructor Create(Source : TStream; AUseUTF8 : Boolean = True); overload;
+ constructor Create(const Source : String; AUseUTF8 : Boolean = True); overload;
destructor Destroy; override;
function FetchToken: TJSONToken;
@@ -80,6 +81,8 @@ type
property CurTokenString: string read FCurTokenString;
// Use strict JSON: " for strings, object members are strings, not identifiers
Property Strict : Boolean Read FStrict Write FStrict;
+ // if set to TRUE, then strings will be converted to UTF8 ansistrings, not system codepage ansistrings.
+ Property UseUTF8 : Boolean Read FUseUTF8 Write FUseUTF8;
end;
const
@@ -104,17 +107,19 @@ const
implementation
-constructor TJSONScanner.Create(Source : TStream);
+constructor TJSONScanner.Create(Source : TStream; AUseUTF8 : Boolean = True);
begin
FSource:=TStringList.Create;
FSource.LoadFromStream(Source);
+ FUseUTF8:=AUseUTF8;
end;
-constructor TJSONScanner.Create(const Source : String);
+constructor TJSONScanner.Create(const Source : String; AUseUTF8 : Boolean = True);
begin
FSource:=TStringList.Create;
FSource.Text:=Source;
+ FUseUTF8:=AUseUTF8;
end;
destructor TJSONScanner.Destroy;
@@ -235,8 +240,11 @@ begin
Error(SErrInvalidCharacter, [CurRow,CurColumn,TokenStr[0]]);
end;
end;
- // Takes care of conversion...
- S:=WideChar(StrToInt('$'+S));
+ // WideChar takes care of conversion...
+ if UseUTF8 then
+ S:=Utf8Encode(WideString(WideChar(StrToInt('$'+S))))
+ else
+ S:=WideChar(StrToInt('$'+S));
end;
#0 : Error(SErrOpenString);
else
diff --git a/mips/packages/fcl-passrc/src/pastree.pp b/mips/packages/fcl-passrc/src/pastree.pp
index aacca82f94..71c2b7f2da 100644
--- a/mips/packages/fcl-passrc/src/pastree.pp
+++ b/mips/packages/fcl-passrc/src/pastree.pp
@@ -103,6 +103,7 @@ type
FName: string;
FParent: TPasElement;
FHints : TPasMemberHints;
+ FHintMessage : String;
protected
procedure ProcessHints(const ASemiColonPrefix: boolean; var AResult: string); virtual;
public
@@ -125,6 +126,7 @@ type
property Parent: TPasElement read FParent;
Property Hints : TPasMemberHints Read FHints Write FHints;
Property CustomData : TObject Read FData Write FData;
+ Property HintMessage : String Read FHintMessage Write FHintMessage;
end;
TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst, pekRange,
@@ -494,7 +496,7 @@ type
- TArgumentAccess = (argDefault, argConst, argVar, argOut);
+ TArgumentAccess = (argDefault, argConst, argVar, argOut, argConstRef);
{ TPasArgument }
@@ -506,7 +508,8 @@ type
public
Access: TArgumentAccess;
ArgType: TPasType;
- Value: string;
+ ValueExpr: TPasExpr;
+ Function Value : String;
end;
{ TPasProcedureType }
@@ -522,6 +525,7 @@ type
function CreateArgument(const AName, AUnresolvedTypeName: string):TPasArgument;
public
IsOfObject: Boolean;
+ IsNested : Boolean;
Args: TFPList; // List of TPasArgument objects
CallingConvention : TCallingConvention;
end;
@@ -1029,7 +1033,7 @@ type
end;
const
- AccessNames: array[TArgumentAccess] of string[6] = ('', 'const ', 'var ', 'out ');
+ AccessNames: array[TArgumentAccess] of string[9] = ('', 'const ', 'var ', 'out ','constref ');
AllVisibilities: TPasMemberVisibilities =
[visDefault, visPrivate, visProtected, visPublic,
visPublished, visAutomated];
@@ -1452,6 +1456,7 @@ destructor TPasArgument.Destroy;
begin
if Assigned(ArgType) then
ArgType.Release;
+ FreeAndNil(ValueExpr);
inherited Destroy;
end;
@@ -2128,7 +2133,9 @@ begin
S.Add(TypeName);
GetArguments(S);
If IsOfObject then
- S.Add(' of object');
+ S.Add(' of object')
+ else if IsNested then
+ S.Add(' is nested');
If Full then
Result:=IndentStrings(S,Length(S[0])+Length(S[1])+1)
else
@@ -2446,6 +2453,14 @@ begin
Result:='';
end;
+function TPasArgument.Value: String;
+begin
+ If Assigned(ValueExpr) then
+ Result:=ValueExpr.GetDeclaration(true)
+ else
+ Result:='';
+end;
+
{ TPassTreeVisitor }
diff --git a/mips/packages/fcl-passrc/src/pparser.pp b/mips/packages/fcl-passrc/src/pparser.pp
index 42013d456f..d4b3649aef 100644
--- a/mips/packages/fcl-passrc/src/pparser.pp
+++ b/mips/packages/fcl-passrc/src/pparser.pp
@@ -36,11 +36,13 @@ resourcestring
SParserExpectedCommaRBracket = 'Expected "," or ")"';
SParserExpectedCommaSemicolon = 'Expected "," or ";"';
SParserExpectedCommaColon = 'Expected "," or ":"';
+ SParserOnlyOneArgumentCanHaveDefault = 'A default value can only be assigned to 1 parameter';
SParserExpectedLBracketColon = 'Expected "(" or ":"';
SParserExpectedLBracketSemicolon = 'Expected "(" or ";"';
SParserExpectedColonSemicolon = 'Expected ":" or ";"';
SParserExpectedSemiColonEnd = 'Expected ";" or "End"';
SParserExpectedConstVarID = 'Expected "const", "var" or identifier';
+ SParserExpectedNested = 'Expected nested keyword';
SParserExpectedColonID = 'Expected ":" or identifier';
SParserSyntaxError = 'Syntax error';
SParserTypeSyntaxError = 'Syntax error in type';
@@ -54,6 +56,7 @@ resourcestring
SLogStartImplementation = 'Start parsing implementation section.';
SLogStartInterface = 'Start parsing interface section';
+ SParsingUsedUnit = 'Parsing used unit "%s" with commandLine "%s"';
type
TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
@@ -656,7 +659,17 @@ begin
NextToken;
Found:=IsCurTokenHint(h);
If Found then
- Include(Result,h)
+ begin
+ Include(Result,h);
+ if (h=hDeprecated) then
+ begin
+ NextToken;
+ if (Curtoken<>tkString) then
+ UnGetToken
+ else
+ Element.HintMessage:=CurTokenString;
+ end;
+ end;
Until Not Found;
UnGetToken;
If Assigned(Element) then
@@ -2323,79 +2336,101 @@ procedure TPasParser.ParseArgList(Parent: TPasElement; Args: TFPList; EndToken:
var
ArgNames: TStringList;
IsUntyped: Boolean;
- Name, Value: String;
+ Name : String;
+ Value : TPasExpr;
i: Integer;
Arg: TPasArgument;
Access: TArgumentAccess;
ArgType: TPasType;
begin
- while True do
- begin
- ArgNames := TStringList.Create;
- Access := argDefault;
- IsUntyped := False;
- ArgType := nil;
+ ArgNames := TStringList.Create;
+ try
while True do
begin
- NextToken;
- if CurToken = tkConst then
- begin
- Access := argConst;
- Name := ExpectIdentifier;
- end else if CurToken = tkVar then
- begin
- Access := ArgVar;
- Name := ExpectIdentifier;
- end else if (CurToken = tkIdentifier) and (UpperCase(CurTokenString) = 'OUT') then
+ ArgNames.Clear;
+ Access := argDefault;
+ IsUntyped := False;
+ ArgType := nil;
+ while True do
begin
- Access := ArgOut;
- Name := ExpectIdentifier;
- end else if CurToken = tkIdentifier then
- Name := CurTokenString
- else
- ParseExc(SParserExpectedConstVarID);
- ArgNames.Add(Name);
- NextToken;
- if CurToken = tkColon then
- break
- else if ((CurToken = tkSemicolon) or (CurToken = tkBraceClose)) and
- (Access <> argDefault) then
- begin
- // found an untyped const or var argument
- UngetToken;
- IsUntyped := True;
- break
- end
- else if CurToken <> tkComma then
- ParseExc(SParserExpectedCommaColon);
- end;
- SetLength(Value, 0);
- if not IsUntyped then
- begin
- ArgType := ParseType(nil);
- NextToken;
- if CurToken = tkEqual then
+ NextToken;
+ if CurToken = tkConst then
+ begin
+ Access := argConst;
+ Name := ExpectIdentifier;
+ end else if CurToken = tkConstRef then
+ begin
+ Access := argConstref;
+ Name := ExpectIdentifier;
+ end else if CurToken = tkVar then
+ begin
+ Access := ArgVar;
+ Name := ExpectIdentifier;
+ end else if (CurToken = tkIdentifier) and (UpperCase(CurTokenString) = 'OUT') then
+ begin
+ Access := ArgOut;
+ Name := ExpectIdentifier;
+ end else if CurToken = tkIdentifier then
+ Name := CurTokenString
+ else
+ ParseExc(SParserExpectedConstVarID);
+ ArgNames.Add(Name);
+ NextToken;
+ if CurToken = tkColon then
+ break
+ else if ((CurToken = tkSemicolon) or (CurToken = tkBraceClose)) and
+ (Access <> argDefault) then
+ begin
+ // found an untyped const or var argument
+ UngetToken;
+ IsUntyped := True;
+ break
+ end
+ else if CurToken <> tkComma then
+ ParseExc(SParserExpectedCommaColon);
+ end;
+ Value:=Nil;
+ if not IsUntyped then
+ begin
+ ArgType := ParseType(nil);
+ try
+ NextToken;
+ if CurToken = tkEqual then
+ begin
+ if (ArgNames.Count>1) then
+ begin
+ FreeAndNil(ArgType);
+ ParseExc(SParserOnlyOneArgumentCanHaveDefault);
+ end;
+ NextToken;
+ Value := DoParseExpression(Parent,Nil);
+ // After this, we're on ), which must be unget.
+ end;
+ UngetToken;
+ except
+ FreeAndNil(ArgType);
+ Raise;
+ end;
+ end;
+
+ for i := 0 to ArgNames.Count - 1 do
begin
- Value := ParseExpression(Parent);
- end else
- UngetToken;
- end;
+ Arg := TPasArgument(CreateElement(TPasArgument, ArgNames[i], Parent));
+ Arg.Access := Access;
+ Arg.ArgType := ArgType;
+ if (i > 0) and Assigned(ArgType) then
+ ArgType.AddRef;
+ Arg.ValueExpr := Value;
+ Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
+ Args.Add(Arg);
+ end;
- for i := 0 to ArgNames.Count - 1 do
- begin
- Arg := TPasArgument(CreateElement(TPasArgument, ArgNames[i], Parent));
- Arg.Access := Access;
- Arg.ArgType := ArgType;
- if (i > 0) and Assigned(ArgType) then
- ArgType.AddRef;
- Arg.Value := Value;
- Args.Add(Arg);
+ NextToken;
+ if CurToken = EndToken then
+ break;
end;
-
+ finally
ArgNames.Free;
- NextToken;
- if CurToken = EndToken then
- break;
end;
end;
@@ -2458,7 +2493,7 @@ begin
begin
NextToken;
if (CurToken = tkSemicolon) or IsCurtokenHint
- or (OfObjectPossible and (CurToken in [tkOf,tkEqual]))
+ or (OfObjectPossible and (CurToken in [tkOf,tkis,tkEqual]))
then
UngetToken
else
@@ -2483,15 +2518,25 @@ begin
ParseType(nil);
end;
end;
-
- NextToken;
- if OfObjectPossible and (CurToken = tkOf) then
- begin
- ExpectToken(tkObject);
- Element.IsOfObject := True;
- end else
- UngetToken;
-
+
+ if OfObjectPossible then
+ begin
+ NextToken;
+ if (curToken =tkOf) then
+ begin
+ ExpectToken(tkObject);
+ Element.IsOfObject := True;
+ end
+ else if (curToken = tkIs) then
+ begin
+ expectToken(tkIdentifier);
+ if (lowerCase(CurTokenString)<>'nested') then
+ ParseExc(SParserExpectedNested);
+ Element.isNested:=True;
+ end
+ else
+ UnGetToken;
+ end;
NextToken;
if CurToken = tkEqual then
begin
@@ -2567,6 +2612,14 @@ begin
if IsCurTokenHint(ahint) then // deprecated,platform,experimental,library, unimplemented etc
begin
element.hints:=element.hints+[ahint];
+ if aHint=hDeprecated then
+ begin
+ nextToken;
+ if (CurToken<>tkString) then
+ UnGetToken
+ else
+ element.HintMessage:=curtokenstring;
+ end;
consumesemi;
end
else if (tok = 'PUBLIC') then
diff --git a/mips/packages/fcl-passrc/src/pscanner.pp b/mips/packages/fcl-passrc/src/pscanner.pp
index 454d93e7ca..044105dcd0 100644
--- a/mips/packages/fcl-passrc/src/pscanner.pp
+++ b/mips/packages/fcl-passrc/src/pscanner.pp
@@ -87,6 +87,7 @@ type
tkcase,
tkclass,
tkconst,
+ tkconstref,
tkconstructor,
tkdestructor,
tkdiv,
@@ -412,6 +413,7 @@ const
'case',
'class',
'const',
+ 'constref',
'constructor',
'destructor',
'div',
diff --git a/mips/packages/fcl-process/src/dummy/pipes.inc b/mips/packages/fcl-process/src/dummy/pipes.inc
index d2fe3eeb0d..0ba622be88 100644
--- a/mips/packages/fcl-process/src/dummy/pipes.inc
+++ b/mips/packages/fcl-process/src/dummy/pipes.inc
@@ -15,7 +15,7 @@
// No pipes under dos, sorry...
-Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle; APipeBufferSize : Cardinal = 1024) : Boolean;
begin
InHandle := THandle (UnusedHandle);
diff --git a/mips/packages/fcl-process/src/os2/pipes.inc b/mips/packages/fcl-process/src/os2/pipes.inc
index ec92e1aa6a..352cf4c793 100644
--- a/mips/packages/fcl-process/src/os2/pipes.inc
+++ b/mips/packages/fcl-process/src/os2/pipes.inc
@@ -19,10 +19,10 @@ uses
const
PipeBufSize = 1024;
-Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint; APipeBufferSize : Cardinal = 1024) : Boolean;
begin
- CreatePipeHandles := DosCreatePipe (InHandle, OutHandle, PipeBufSize) = 0;
+ CreatePipeHandles := DosCreatePipe (InHandle, OutHandle, APipeBufferSize) = 0;
end;
Function TInputPipeStream.GetNumBytesAvailable: DWord;
diff --git a/mips/packages/fcl-process/src/pipes.pp b/mips/packages/fcl-process/src/pipes.pp
index a52123e696..555961d34b 100644
--- a/mips/packages/fcl-process/src/pipes.pp
+++ b/mips/packages/fcl-process/src/pipes.pp
@@ -50,7 +50,7 @@ Type
Function Read (Var Buffer; Count : Longint) : longint; Override;
end;
-Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle; APipeBufferSize : Cardinal = 1024) : Boolean;
Procedure CreatePipeStreams (Var InPipe : TInputPipeStream;
Var OutPipe : TOutputPipeStream);
diff --git a/mips/packages/fcl-process/src/process.pp b/mips/packages/fcl-process/src/process.pp
index 5ec6b1d4cf..bc30c05171 100644
--- a/mips/packages/fcl-process/src/process.pp
+++ b/mips/packages/fcl-process/src/process.pp
@@ -78,6 +78,7 @@ Type
dwYcountChars,
dwy : Cardinal;
FXTermProgram: String;
+ FPipeBufferSize : cardinal;
Procedure FreeStreams;
Function GetExitStatus : Integer;
Function GetRunning : Boolean;
@@ -134,6 +135,7 @@ Type
property OnForkEvent : TProcessForkEvent Read FForkEvent Write FForkEvent;
{$endif UNIX}
Published
+ property PipeBufferSize : cardinal read FPipeBufferSize write FPipeBufferSize default 1024;
Property Active : Boolean Read GetRunning Write SetActive;
Property ApplicationName : String Read FApplicationName Write SetApplicationName; deprecated;
Property CommandLine : String Read FCommandLine Write SetCommandLine ; deprecated;
@@ -247,6 +249,7 @@ begin
{$ifdef UNIX}
FForkEvent:=nil;
{$endif UNIX}
+ FPipeBufferSize := 1024;
FEnvironment:=TStringList.Create;
FParameters:=TStringList.Create;
end;
@@ -465,8 +468,8 @@ begin
try
try
p.Options := [poUsePipes];
- p.Execute;
bytesread:=0;
+ p.Execute;
while p.Running do
begin
Setlength(outputstring,BytesRead + READ_BYTES);
diff --git a/mips/packages/fcl-process/src/unix/pipes.inc b/mips/packages/fcl-process/src/unix/pipes.inc
index 8d2e691aa1..269ab12dbc 100644
--- a/mips/packages/fcl-process/src/unix/pipes.inc
+++ b/mips/packages/fcl-process/src/unix/pipes.inc
@@ -16,7 +16,7 @@
Uses
BaseUnix, Unix, TermIO;
-Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint; APipeBufferSize : Cardinal = 1024) : Boolean;
begin
Result := (AssignPipe (Inhandle,OutHandle)<>-1);
diff --git a/mips/packages/fcl-process/src/unix/process.inc b/mips/packages/fcl-process/src/unix/process.inc
index 2d57d0053b..1339b6460c 100644
--- a/mips/packages/fcl-process/src/unix/process.inc
+++ b/mips/packages/fcl-process/src/unix/process.inc
@@ -52,7 +52,7 @@ begin
// else pass errorvalue unmodified like shell does, bug #22055
end
else
- FexitCode:=-1; // was 0, better testable for abnormal exit.
+ FexitCode:=cardinal(-1); // was 0, better testable for abnormal exit.
end;
Type
diff --git a/mips/packages/fcl-process/src/win/pipes.inc b/mips/packages/fcl-process/src/win/pipes.inc
index 76f4154a98..899ec5a527 100644
--- a/mips/packages/fcl-process/src/win/pipes.inc
+++ b/mips/packages/fcl-process/src/win/pipes.inc
@@ -28,10 +28,10 @@ Const piInheritablePipe : TSecurityAttributes = (
PipeBufSize = 1024;
-Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle; APipeBufferSize : Cardinal = PipeBufSize) : Boolean;
begin
- Result := CreatePipe (@Inhandle,@OutHandle,@piNonInheritablePipe,PipeBufSize);
+ Result := CreatePipe (@Inhandle,@OutHandle,@piNonInheritablePipe,APipeBufferSize);
end;
diff --git a/mips/packages/fcl-process/src/win/process.inc b/mips/packages/fcl-process/src/win/process.inc
index b0c532e10a..58b8eafda7 100644
--- a/mips/packages/fcl-process/src/win/process.inc
+++ b/mips/packages/fcl-process/src/win/process.inc
@@ -179,15 +179,15 @@ begin
end;
-Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean);
+Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean; APipeBufferSize : Cardinal);
begin
- CreatePipeHandles(SI.hStdInput,HI);
+ CreatePipeHandles(SI.hStdInput,HI, APipeBufferSize);
DuplicateHandleFP(SI.hStdInput);
- CreatePipeHandles(HO,Si.hStdOutput);
+ CreatePipeHandles(HO,Si.hStdOutput, APipeBufferSize);
DuplicateHandleFP( Si.hStdOutput);
if CE then begin
- CreatePipeHandles(HE,SI.hStdError);
+ CreatePipeHandles(HE,SI.hStdError, APipeBufferSize);
DuplicateHandleFP( SI.hStdError);
end
else
@@ -262,7 +262,7 @@ begin
InitThreadAttributes(Self,FThreadAttributes);
InitStartupInfo(Self,FStartUpInfo);
If poUsePipes in FProcessOptions then
- CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions));
+ CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions), FPipeBufferSize);
Try
If Not CreateProcess (PName,PCommandLine,@FProcessAttributes,@FThreadAttributes,
FInheritHandles,FCreationFlags,FEnv,PDir,FStartupInfo,
diff --git a/mips/packages/fcl-process/src/wince/process.inc b/mips/packages/fcl-process/src/wince/process.inc
index ed641c0b1f..116c78972e 100644
--- a/mips/packages/fcl-process/src/wince/process.inc
+++ b/mips/packages/fcl-process/src/wince/process.inc
@@ -152,13 +152,13 @@ begin
end;
end;
-Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean);
+Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean; APipeBufferSize : Cardinal);
begin
- CreatePipeHandles(SI.hStdInput,HI);
- CreatePipeHandles(HO,Si.hStdOutput);
+ CreatePipeHandles(SI.hStdInput,HI,APipeBufferSize);
+ CreatePipeHandles(HO,Si.hStdOutput,APipeBufferSize);
if CE then
- CreatePipeHandles(HE,SI.hStdError)
+ CreatePipeHandles(HE,SI.hStdError,APipeBufferSize)
else
begin
SI.hStdError:=SI.hStdOutput;
@@ -213,7 +213,7 @@ begin
InitThreadAttributes(Self,FThreadAttributes);
InitStartupInfo(Self,FStartUpInfo);
If poUsePipes in FProcessOptions then
- CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions));
+ CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions),FPipeBufferSize);
Try
If Not CreateProcess (PName,PCommandLine,@FProcessAttributes,@FThreadAttributes,
FInheritHandles,FCreationFlags,FEnv,PDir,@FStartupInfo,
diff --git a/mips/packages/fcl-web/src/base/httpdefs.pp b/mips/packages/fcl-web/src/base/httpdefs.pp
index 782952bfe4..0d91f3a586 100644
--- a/mips/packages/fcl-web/src/base/httpdefs.pp
+++ b/mips/packages/fcl-web/src/base/httpdefs.pp
@@ -62,11 +62,12 @@ const
NoHTTPFields = 24;
- HTTPDateFmt = '"%s", dd "%s" yyyy hh:mm:ss'; // For use in FormatDateTime
- SCookieExpire = ' "expires="'+HTTPDateFmt+' "GMT;"';
- SCookieDomain = ' domain=%s;';
- SCookiePath = ' path=%s;';
- SCookieSecure = ' secure';
+ HTTPDateFmt = '"%s", dd "%s" yyyy hh:mm:ss'; // For use in FormatDateTime
+ SCookieExpire = ' "Expires="'+HTTPDateFmt+' "GMT"';
+ SCookieDomain = ' Domain=%s';
+ SCookiePath = ' Path=%s';
+ SCookieSecure = ' Secure';
+ SCookieHttpOnly = ' HttpOnly';
HTTPMonths: array[1..12] of string[3] = (
'Jan', 'Feb', 'Mar', 'Apr',
@@ -98,6 +99,7 @@ type
TCookie = class(TCollectionItem)
private
+ FHttpOnly: Boolean;
FName: string;
FValue: string;
FPath: string;
@@ -109,12 +111,14 @@ type
public
constructor Create(ACollection: TCollection); override;
procedure Assign(Source: TPersistent); override;
+ procedure Expire;
property Name: string read FName write FName;
property Value: string read FValue write FValue;
property Domain: string read FDomain write FDomain;
property Path: string read FPath write FPath;
property Expires: TDateTime read FExpires write FExpires;
property Secure: Boolean read FSecure write FSecure;
+ property HttpOnly: Boolean read FHttpOnly write FHttpOnly;
Property AsString : String Read GetAsString;
end;
@@ -290,7 +294,9 @@ type
Procedure ProcessMultiPart(Stream : TStream; Const Boundary : String;SL:TStrings); virtual;
Procedure ProcessQueryString(Const FQueryString : String; SL:TStrings); virtual;
procedure ProcessURLEncoded(Stream : TStream;SL:TStrings); virtual;
- Function GetTempUploadFileName : String; virtual;
+ Function RequestUploadDir : String; virtual;
+ Function GetTempUploadFileName(Const AName, AFileName : String; ASize : Int64) : String; virtual;
+ Procedure DeleteTempUploadedFiles; virtual;
Procedure InitRequestVars; virtual;
Procedure InitPostVars; virtual;
Procedure InitGetVars; virtual;
@@ -427,7 +433,7 @@ Resourcestring
SErrUnknownCookie = 'Unknown cookie: "%s"';
SErrUnsupportedContentType = 'Unsupported content type: "%s"';
SErrNoRequestMethod = 'No REQUEST_METHOD passed from server.';
- SErrInvalidRequestMethod = 'Invalid REQUEST_METHOD passed from server.';
+ SErrInvalidRequestMethod = 'Invalid REQUEST_METHOD passed from server: %s.';
const
hexTable = '0123456789ABCDEF';
@@ -951,18 +957,8 @@ begin
end;
destructor TRequest.destroy;
-var
- i: Integer;
- s: String;
begin
- //delete all temporary uploaded files created for this request if there is any
- i := FFiles.Count;
- if i > 0 then for i := i - 1 downto 0 do
- begin
- s := FFiles[i].LocalFileName;
- if FileExists(s) then DeleteFile(s);
- end;
- //
+ DeleteTempUploadedFiles;
FreeAndNil(FFiles);
inherited destroy;
end;
@@ -1191,18 +1187,36 @@ begin
{$ifdef CGIDEBUG}SendMethodExit('ProcessQueryString');{$endif CGIDEBUG}
end;
-function TRequest.GetTempUploadFileName: String;
+Function TRequest.RequestUploadDir : String;
begin
-//Result:=GetTempFileName('/tmp/','CGI') {Hard coded path no good for all OS-es}
-{
-GetTempDir returns the OS temporary directory if possible, or from the
-environment variable TEMP . For CGI programs you need to pass global environment
- variables, it is not automatic. For example in the Apache httpd.conf with a
-"PassEnv TEMP" or "SetEnv TEMP /pathtotmpdir" line so the web server passes this
- global environment variable to the CGI programs' local environment variables.
-}
- Result := GetTempFileName(GetTempDir, 'CGI');
+ Result:='';
+end;
+
+Function TRequest.GetTempUploadFileName(Const AName, AFileName : String; ASize : Int64): String;
+
+Var
+ D : String;
+
+begin
+ D:=RequestUploadDir;
+ if (D='') then
+ D:=GetTempDir; // Note that this may require a TEMP environment variable to be set by the webserver.
+ Result:=GetTempFileName(D, 'CGI');
+end;
+
+Procedure TRequest.DeleteTempUploadedFiles;
+var
+ i: Integer;
+ s: String;
+begin
+ //delete all temporary uploaded files created for this request if there is any
+ i := FFiles.Count;
+ if i > 0 then for i := i - 1 downto 0 do
+ begin
+ s := FFiles[i].LocalFileName;
+ if FileExists(s) then DeleteFile(s);
+ end;
end;
procedure TRequest.InitRequestVars;
@@ -1223,7 +1237,7 @@ begin
if FHandleGetOnPost then
InitGetVars;
end
- else if (CompareText(R,'GET')=0) or (CompareText(R,'HEAD')=0) then
+ else if (CompareText(R,'GET')=0) or (CompareText(R,'HEAD')=0) or (CompareText(R,'OPTIONS')=0) then
InitGetVars
else
Raise Exception.CreateFmt(SErrInvalidRequestMethod,[R]);
@@ -1356,10 +1370,10 @@ begin
else
begin
FI.DLen:=J;
- FF:=GetTempUploadFileName;
+ FF:=GetTempUploadFileName(FI.name,FI.FileName,J);
F:=TFileStream.Create(FF,fmCreate);
Try
- F.Write(FI.Data[1],Length(FI.Data));
+ F.Write(FI.Data[1],J);
finally
F.Free;
end;
@@ -1655,29 +1669,37 @@ end;
function TCookie.GetAsString: string;
+ Procedure AddToResult(S : String);
+
+ begin
+ Result:=Result+';'+S;
+ end;
+
Var
Y,M,D : Word;
begin
{$ifdef cgidebug}SendMethodEnter('TCookie.GetAsString');{$endif}
try
- Result:=Format('%s=%s;',[HTTPEncode(FName),HTTPEncode(FValue)]);
+ Result:=Format('%s=%s',[HTTPEncode(FName),HTTPEncode(FValue)]);
if (Length(FDomain)>0) then
- Result:=Result+Format(SCookieDomain,[FDomain]);
+ AddToResult(Format(SCookieDomain,[FDomain]));
if (Length(FPath)>0) then
- Result:=Result+Format(SCookiePath,[FPath]);
+ AddToResult(Format(SCookiePath,[FPath]));
if (FExpires>-1) then
begin
DecodeDate(Expires,Y,M,D);
- Result:=Result+Format(FormatDateTime(SCookieExpire,Expires),
- [HTTPDays[DayOfWeek(Expires)],HTTPMonths[M]]);
+ AddToResult(Format(FormatDateTime(SCookieExpire,Expires),
+ [HTTPDays[DayOfWeek(Expires)],HTTPMonths[M]]));
end;
- if Secure then
- Result:=Result+SCookieSecure;
+ if FHttpOnly then
+ AddToResult(SCookieHttpOnly);
+ if FSecure then
+ AddToResult(SCookieSecure);
except
{$ifdef cgidebug}
On E : Exception do
- SendDebug('Exception in cookie asstring : '+E.Message)
+ SendDebug('Exception in cookie AsString: '+E.Message)
{$endif}
end;
{$ifdef cgidebug}SendMethodExit('TCookie.GetAsString');{$endif}
@@ -1699,12 +1721,18 @@ begin
Self.FDomain:=Domain;
Self.FPath:=Path;
Self.FExpires:=Expires;
+ Self.FHttpOnly:=HttpOnly;
Self.FSecure:=Secure;
end
else
inherited Assign(Source);
end;
+procedure TCookie.Expire;
+begin
+ FExpires := EncodeDate(1970, 1, 1);
+end;
+
{ TCookieCollection }
function TCookies.GetCookie(Index: Integer): TCookie;
diff --git a/mips/packages/fcl-web/src/base/iniwebsession.pp b/mips/packages/fcl-web/src/base/iniwebsession.pp
index 738b289b2b..7c31d46072 100644
--- a/mips/packages/fcl-web/src/base/iniwebsession.pp
+++ b/mips/packages/fcl-web/src/base/iniwebsession.pp
@@ -48,6 +48,7 @@ Type
Procedure InitSession(ARequest : TRequest; OnNewSession, OnExpired: TNotifyEvent); override;
Procedure InitResponse(AResponse : TResponse); override;
Procedure RemoveVariable(VariableName : String); override;
+ Function GetSessionDir : String;
end;
TIniWebSessionClass = Class of TIniWebSession;
@@ -68,6 +69,7 @@ Type
// Sweep session direcory and delete expired files.
procedure DoCleanupSessions; override;
Procedure DoDoneSession(Var ASession : TCustomSession); override;
+ Function SessionFilePrefix : String; virtual;
Public
// Directory where sessions are kept.
Property SessionDir : String Read FSessionDir Write SetSessionDir;
@@ -212,8 +214,20 @@ begin
FreeAndNil(ASession);
end;
+Function TIniSessionFactory.SessionFilePrefix : String;
+
+begin
+ Result:='';
+end;
+
{ TIniWebSession }
+Function TIniWebSession.GetSessionDir : String;
+
+begin
+ Result:=SessionDir;
+end;
+
function TIniWebSession.GetSessionID: String;
begin
If (SID='') then
@@ -282,8 +296,10 @@ procedure TIniWebSession.InitSession(ARequest: TRequest; OnNewSession,OnExpired:
Var
S : String;
-
+ SF : TIniSessionFactory;
+
begin
+ SF:=SessionFactory as TIniSessionFactory;
{$ifdef cgidebug}SendMethodEnter('TIniWebSession.InitSession');{$endif}
// First initialize all session-dependent properties to their default, because
// in Apache-modules or fcgi programs the session-instance is re-used
@@ -299,13 +315,13 @@ begin
If (S<>'') then
begin
{$ifdef cgidebug}SendDebug('Reading ini file:'+S);{$endif}
- FIniFile:=TMemIniFile.Create(IncludeTrailingPathDelimiter(SessionDir)+S);
- if (SessionFactory as TIniSessionFactory).SessionExpired(FIniFile) then
+ FIniFile:=TMemIniFile.Create(IncludeTrailingPathDelimiter(SessionDir)+SF.SessionFilePrefix+S);
+ if SF.SessionExpired(FIniFile) then
begin
// Expire session.
If Assigned(OnExpired) then
OnExpired(Self);
- (SessionFactory as TIniSessionFactory).DeleteSessionFile(FIniFIle.FileName);
+ SF.DeleteSessionFile(FIniFIle.FileName);
FreeAndNil(FInifile);
S:='';
end
@@ -317,7 +333,7 @@ begin
If Assigned(OnNewSession) then
OnNewSession(Self);
GetSessionID;
- S:=IncludeTrailingPathDelimiter(SessionDir)+SessionID;
+ S:=IncludeTrailingPathDelimiter(SessionDir)+SF.SessionFilePrefix+SessionID;
{$ifdef cgidebug}SendDebug('Creating new Ini file : '+S);{$endif}
FIniFile:=TMemIniFile.Create(S);
FIniFile.WriteDateTime(SSession,KeyStart,Now);
diff --git a/mips/packages/fpindexer/src/dbindexer.pp b/mips/packages/fpindexer/src/dbindexer.pp
index 2cfb044119..618d3d733a 100644
--- a/mips/packages/fpindexer/src/dbindexer.pp
+++ b/mips/packages/fpindexer/src/dbindexer.pp
@@ -394,6 +394,7 @@ Var
begin
Result:=0;
+ T:='';
R:=TIReaderTXT.Create;
try
URL:=TableName+'/'+KeyField.AsString;
diff --git a/mips/packages/libpng/src/png.pp b/mips/packages/libpng/src/png.pp
index 2924830a86..156d66b522 100644
--- a/mips/packages/libpng/src/png.pp
+++ b/mips/packages/libpng/src/png.pp
@@ -25,6 +25,7 @@ Const
LibPng = 'png'; // Library name
{ matching lib version for libpng, needed for initialization }
PNG_LIBPNG_VER_STRING='1.2.12';
+ {$linklib png}
{$endif windows}
type
diff --git a/mips/packages/winunits-base/src/eventsink.pp b/mips/packages/winunits-base/src/eventsink.pp
index c6bad57a2c..f2777a9d5c 100644
--- a/mips/packages/winunits-base/src/eventsink.pp
+++ b/mips/packages/winunits-base/src/eventsink.pp
@@ -41,7 +41,9 @@ type
const IID: TGUID; LocaleID: Integer; Flags: Word;
Params: TDispParams; VarResult, ExcepInfo, ArgErr: Pointer) of object;
- TAbstractEventSink = class(TInterfacedObject, IDispatch)
+ { TAbstractEventSink }
+
+ TAbstractEventSink = class(TObject, IDispatch,IUnknown) // see mantis #22156
private
FDispatch: IDispatch;
FDispIntfIID: TGUID;
@@ -49,7 +51,10 @@ type
FOwner: TComponent;
protected
{ IUnknown }
+ frefcount : longint;
function QueryInterface(constref IID: TGUID; out Obj): HRESULT; stdcall;
+ function _AddRef : longint;stdcall;
+ function _Release : longint;stdcall;
{ IDispatch }
function GetTypeInfoCount(out Count: Integer): HRESULT; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HRESULT; stdcall;
@@ -166,6 +171,20 @@ begin
Result := S_OK;
end;
+function TAbstractEventSink._AddRef: longint; stdcall;
+begin
+ frefcount:=frefcount+1;
+ _addref:=frefcount;
+end;
+
+function TAbstractEventSink._Release: longint; stdcall;
+begin
+ frefcount:=frefcount-1;
+ _Release:=frefcount;
+ if frefcount=0 then
+ self.destroy;
+end;
+
procedure TAbstractEventSink.Connect(AnAppDispatch: IDispatch;
const AnAppDispIntfIID: TGUID);
begin
diff --git a/mips/rtl/arm/arm.inc b/mips/rtl/arm/arm.inc
index 3387ff8e16..65bcb64d1f 100644
--- a/mips/rtl/arm/arm.inc
+++ b/mips/rtl/arm/arm.inc
@@ -52,7 +52,7 @@ begin
// mask "exception happened" and overflow flags
and r0,r0,#0xffffff20
// mask exception flags
- and r0,r0,#0xffff40ff
+ and r0,r0,#0xffff40ff
{$ifndef darwin}
// Floating point exceptions cause kernel panics on iPhoneOS 2.2.1...
@@ -110,7 +110,7 @@ end;
{$ENDIF not INTERNAL_BACKTRACE}
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
asm
cmp r0,#0
{$ifndef darwin}
@@ -122,7 +122,7 @@ end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
asm
cmp r0,#0
{$ifndef darwin}
@@ -145,62 +145,69 @@ end;
Procedure FillChar(var x;count:longint;value:byte);assembler;nostackframe;
asm
// less than 0?
- cmp r1,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
- movlt pc,lr
+ cmp r1,#0
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
+ movle pc,lr
{$else}
- bxlt lr
+ bxle lr
{$endif}
mov r3,r0
- cmp r1,#8 // at least 8 bytes to do?
- blt .LFillchar2
- orr r2,r2,r2,lsl #8
- orr r2,r2,r2,lsl #16
-.LFillchar0:
- tst r3,#3 // aligned yet?
- strneb r2,[r3],#1
- subne r1,r1,#1
- bne .LFillchar0
+
+ orr r2,r2,r2,lsl #8
+ orr r2,r2,r2,lsl #16
+
+ tst r3, #3 // Aligned?
+ bne .LFillchar_do_align
+
+.LFillchar_is_aligned:
+ subs r1,r1,#8
+ bmi .LFillchar_less_than_8bytes
+
mov ip,r2
-.LFillchar1:
- cmp r1,#8 // 8 bytes still to do?
- blt .LFillchar2
- stmia r3!,{r2,ip}
- sub r1,r1,#8
- cmp r1,#8 // 8 bytes still to do?
- blt .LFillchar2
+.LFillchar_at_least_8bytes:
+ // Do 16 bytes per loop
+ // More unrolling is uncessary, as we'll just stall on the write buffers
stmia r3!,{r2,ip}
- sub r1,r1,#8
- cmp r1,#8 // 8 bytes still to do?
- blt .LFillchar2
- stmia r3!,{r2,ip}
- sub r1,r1,#8
- cmp r1,#8 // 8 bytes still to do?
- stmgeia r3!,{r2,ip}
- subge r1,r1,#8
- bge .LFillchar1
-.LFillchar2:
- movs r1,r1 // anything left?
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+ subs r1,r1,#8
+ stmplia r3!,{r2,ip}
+ subpls r1,r1,#8
+ bpl .LFillchar_at_least_8bytes
+
+.LFillchar_less_than_8bytes:
+ // Do the rest
+ adds r1, r1, #8
+
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
moveq pc,lr
{$else}
bxeq lr
{$endif}
- rsb r1,r1,#7
- add pc,pc,r1,lsl #2
- mov r0,r0
- strb r2,[r3],#1
- strb r2,[r3],#1
- strb r2,[r3],#1
- strb r2,[r3],#1
- strb r2,[r3],#1
- strb r2,[r3],#1
- strb r2,[r3],#1
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+
+ tst r1, #4
+ strne r2,[r3],#4
+ tst r1, #2
+ strneh r2,[r3],#2
+ tst r1, #1
+ strneb r2,[r3],#1
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc,lr
{$else}
bx lr
{$endif}
+
+// Special case for unaligned start
+// We make a maximum of 3 loops here
+.LFillchar_do_align:
+ strb r2,[r3],#1
+ subs r1, r1, #1
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
+ moveq pc,lr
+{$else}
+ bxeq lr
+{$endif}
+ tst r3,#3
+ bne .LFillchar_do_align
+ b .LFillchar_is_aligned
end;
{$endif FPC_SYSTEM_HAS_FILLCHAR}
@@ -211,7 +218,7 @@ asm
pld [r0]
// count <=0 ?
cmp r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
movle pc,lr
{$else}
bxle lr
@@ -228,7 +235,7 @@ asm
ldrb r3,[r0,r2]
strb r3,[r1,r2]
bne .Loverlapped
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc,lr
{$else}
bx lr
@@ -273,7 +280,7 @@ asm
str r3,[r1],#4
bcs .Ldwordloop
cmp r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
moveq pc,lr
{$else}
bxeq lr
@@ -283,7 +290,7 @@ asm
ldrb r3,[r0],#1
strb r3,[r1],#1
bne .Lbyteloop
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc,lr
{$else}
bx lr
@@ -294,7 +301,7 @@ procedure Move_blended(const source;var dest;count:longint);assembler;nostackfra
asm
// count <=0 ?
cmp r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
movle pc,lr
{$else}
bxle lr
@@ -311,7 +318,7 @@ asm
ldrb r3,[r0,r2]
strb r3,[r1,r2]
bne .Loverlapped
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc,lr
{$else}
bx lr
@@ -353,7 +360,7 @@ asm
str r3,[r1],#4
bcs .Ldwordloop
cmp r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
moveq pc,lr
{$else}
bxeq lr
@@ -363,7 +370,7 @@ asm
ldrb r3,[r0],#1
strb r3,[r1],#1
bne .Lbyteloop
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc,lr
{$else}
bx lr
@@ -542,7 +549,7 @@ asm
terminating 0, due to the known carry flag sbc can do this.*)
sbc r0,r1,r0
.Ldone:
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc,lr
{$else}
bx lr
diff --git a/mips/rtl/arm/divide.inc b/mips/rtl/arm/divide.inc
index 8df2a6524f..42dfe7dd58 100644
--- a/mips/rtl/arm/divide.inc
+++ b/mips/rtl/arm/divide.inc
@@ -96,7 +96,7 @@ asm
.Ldiv_next:
bcs .Ldiv_loop
mov r0, r3
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc, lr
{$else}
bx lr
@@ -105,7 +105,7 @@ asm
mov r0, #200
mov r1, r11
bl handleerrorframe
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
mov pc, lr
{$else}
bx lr
diff --git a/mips/rtl/arm/strings.inc b/mips/rtl/arm/strings.inc
index 388f2e0626..f3512975b6 100644
--- a/mips/rtl/arm/strings.inc
+++ b/mips/rtl/arm/strings.inc
@@ -15,3 +15,50 @@
**********************************************************************}
+{$ifndef FPC_UNIT_HAS_STRUPPER}
+{$define FPC_UNIT_HAS_STRUPPER}
+function strupper(p : pchar) : pchar;assembler;nostackframe;
+asm
+ mov ip, r0 // Don't change r0, because thats our return value
+
+ ldrb r1, [ip] // First loop does not postindex
+.LByteLoop:
+ cmp r1, #0
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
+ moveq pc, lr
+{$else}
+ bxeq lr
+{$endif}
+
+ sub r2, r1, #97 // Normalize to zero
+ cmp r2, #25 // temp >= 0 and temp <=25
+ subls r1, r1, #32 // is lowercase, make uppercase
+ strlsb r1, [ip] // Store only on change
+ ldrb r1, [ip, #1]! // Loading here utilizes a load delay slot
+ b .LByteLoop
+end;
+{$endif FPC_UNIT_HAS_STRUPPER}
+
+{$ifndef FPC_UNIT_HAS_STRLOWER}
+{$define FPC_UNIT_HAS_STRLOWER}
+function strlower(p : pchar) : pchar;assembler;nostackframe;
+asm
+ mov ip, r0 // Don't change r0, because thats our return value
+
+ ldrb r1, [ip] // First loop does not postindex
+.LByteLoop:
+ cmp r1, #0
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
+ moveq pc, lr
+{$else}
+ bxeq lr
+{$endif}
+
+ sub r2, r1, #65 // Normalize to zero
+ cmp r2, #25 // temp >= 0 and temp <=25
+ addls r1, r1, #32 // Is uppercase, make lowercase
+ strlsb r1, [ip] // Store only on change
+ ldrb r1, [ip, #1]! // Loading here utilizes a load delay slot
+ b .LByteLoop
+end;
+{$endif FPC_UNIT_HAS_STRLOWER}
diff --git a/mips/rtl/avr/avr.inc b/mips/rtl/avr/avr.inc
index e9d93e85b1..2ad61f5a07 100644
--- a/mips/rtl/avr/avr.inc
+++ b/mips/rtl/avr/avr.inc
@@ -38,13 +38,13 @@ function get_frame:pointer;assembler;nostackframe;
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;assembler;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;
asm
end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;assembler;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;
asm
end;
diff --git a/mips/rtl/i386/i386.inc b/mips/rtl/i386/i386.inc
index 368c7a02f4..9fb8a7d724 100644
--- a/mips/rtl/i386/i386.inc
+++ b/mips/rtl/i386/i386.inc
@@ -1061,8 +1061,14 @@ end;
{$ENDIF not INTERNAL_BACKTRACE}
+{$define FPC_SYSTEM_HAS_GET_PC_ADDR}
+Function Get_pc_addr : Pointer;assembler;nostackframe;
+asm
+ movl (%esp),%eax
+end;
+
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;nostackframe;assembler;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;nostackframe;assembler;
asm
orl %eax,%eax
jz .Lg_a_null
@@ -1072,7 +1078,7 @@ end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;nostackframe;assembler;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;nostackframe;assembler;
asm
orl %eax,%eax
jz .Lgnf_null
diff --git a/mips/rtl/inc/compproc.inc b/mips/rtl/inc/compproc.inc
index 0a7d9ccc7f..8024c715d3 100644
--- a/mips/rtl/inc/compproc.inc
+++ b/mips/rtl/inc/compproc.inc
@@ -40,6 +40,7 @@ procedure fpc_zeromem(p:pointer;len:ptruint);compilerproc;
procedure fpc_fillmem(out data;len:ptruint;b : byte);compilerproc;
procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt); compilerproc;
+procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer); compilerproc;
procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring); compilerproc;
procedure fpc_shortstr_concat(var dests:shortstring;const s1,s2:shortstring);compilerproc;
@@ -421,7 +422,7 @@ procedure fpc_variant_init(var v: tvardata);compilerproc;
procedure fpc_variant_clear(var v: tvardata);compilerproc;
{$ifdef FPC_VARIANTCOPY_FIXED}
procedure fpc_variant_copy(var d: tvardata; const s : tvardata);compilerproc;
-procedure fpc_variant_copy_overwrite(const source: tvardata; var dest : tvardata);compilerproc;
+procedure fpc_variant_copy_overwrite(constref source: tvardata; var dest : tvardata);compilerproc;
{$else FPC_VARIANTCOPY_FIXED}
procedure fpc_variant_copy(d,s : pointer);compilerproc;
procedure fpc_variant_copy_overwrite(source, dest : pointer);compilerproc;
diff --git a/mips/rtl/inc/except.inc b/mips/rtl/inc/except.inc
index e1b4839d8a..e9343dfcb3 100644
--- a/mips/rtl/inc/except.inc
+++ b/mips/rtl/inc/except.inc
@@ -102,6 +102,7 @@ var
frames : PPointer;
prev_frame,
curr_frame,
+ curr_addr,
caller_frame,
caller_addr : Pointer;
begin
@@ -119,15 +120,16 @@ begin
{ Backtrace }
curr_frame:=AFrame;
- prev_frame:=get_frame;
+ curr_addr:=AnAddr;
+ prev_frame:=get_caller_frame(curr_addr, curr_frame);
frames:=nil;
framebufsize:=0;
framecount:=0;
while (framecount<RaiseMaxFrameCount) and (curr_frame > prev_frame) and
(curr_frame<(StackBottom + StackLength)) do
Begin
- caller_addr := get_caller_addr(curr_frame);
- caller_frame := get_caller_frame(curr_frame);
+ caller_addr := get_caller_addr(curr_frame, curr_addr);
+ caller_frame := get_caller_frame(curr_frame, curr_addr);
if (caller_addr=nil) or
(caller_frame=nil) then
break;
@@ -139,6 +141,7 @@ begin
frames[framecount]:=caller_addr;
inc(framecount);
prev_frame:=curr_frame;
+ curr_addr:=caller_addr;
curr_frame:=caller_frame;
End;
NewObj^.framecount:=framecount;
diff --git a/mips/rtl/inc/generic.inc b/mips/rtl/inc/generic.inc
index 87e0a46699..7c351a666c 100644
--- a/mips/rtl/inc/generic.inc
+++ b/mips/rtl/inc/generic.inc
@@ -892,7 +892,7 @@ begin
res[0]:=chr(slen);
end;
-procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN'];
+procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN']; compilerproc;
var
slen : byte;
begin
diff --git a/mips/rtl/inc/heaptrc.pp b/mips/rtl/inc/heaptrc.pp
index 9963a40e01..1099cc5927 100644
--- a/mips/rtl/inc/heaptrc.pp
+++ b/mips/rtl/inc/heaptrc.pp
@@ -331,14 +331,21 @@ end;
procedure dump_already_free(p : pheap_mem_info;var ptext : text);
+var
+ bp, pcaddr : pointer;
begin
Writeln(ptext,'Marked memory at $',HexStr(pointer(p)+sizeof(theap_mem_info)),' released');
call_free_stack(p,ptext);
Writeln(ptext,'freed again at');
- dump_stack(ptext,get_caller_frame(get_frame));
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
+ dump_stack(ptext,bp,pcaddr);
end;
procedure dump_error(p : pheap_mem_info;var ptext : text);
+var
+ bp, pcaddr : pointer;
begin
Writeln(ptext,'Marked memory at $',HexStr(pointer(p)+sizeof(theap_mem_info)),' invalid');
Writeln(ptext,'Wrong signature $',hexstr(p^.sig,8),' instead of ',hexstr(calculate_sig(p),8));
@@ -347,7 +354,10 @@ begin
write(ptext, 'Block content: ');
printhex(pointer(p) + sizeof(theap_mem_info), p^.size, ptext);
end;
- dump_stack(ptext,get_caller_frame(get_frame));
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
+ dump_stack(ptext,bp,pcaddr);
end;
{$ifdef EXTRA}
@@ -367,10 +377,15 @@ end;
{$endif EXTRA}
procedure dump_wrong_size(p : pheap_mem_info;size : ptruint;var ptext : text);
+var
+ bp, pcaddr : pointer;
begin
Writeln(ptext,'Marked memory at $',HexStr(pointer(p)+sizeof(theap_mem_info)),' invalid');
Writeln(ptext,'Wrong size : ',p^.size,' allocated ',size,' freed');
- dump_stack(ptext,get_caller_frame(get_frame));
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
+ dump_stack(ptext,bp,pcaddr);
{ the check is done to be sure that the procvar is not overwritten }
if assigned(p^.extra_info) and
(p^.extra_info^.check=$12345678) and
@@ -445,7 +460,7 @@ Function TraceGetMem(size:ptruint):pointer;
var
allocsize,i : ptruint;
oldbp,
- bp : pointer;
+ bp,pcaddr : pointer;
pl : pdword;
p : pointer;
pp : pheap_mem_info;
@@ -509,15 +524,16 @@ begin
{ clear the memory }
fillchar(p^,size,#255);
{ retrieve backtrace info }
- bp:=get_caller_frame(get_frame);
-
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
{ valid bp? }
if (bp>=StackBottom) and (bp<(StackBottom + StackLength)) then
for i:=1 to tracesize do
begin
- pp^.calls[i]:=get_caller_addr(bp);
oldbp:=bp;
- bp:=get_caller_frame(bp);
+ get_caller_stackinfo(bp,pcaddr);
+ pp^.calls[i]:=pcaddr;
if (bp<oldbp) or (bp>(StackBottom + StackLength)) then
break;
end;
@@ -553,7 +569,7 @@ function CheckFreeMemSize(loc_info: pheap_info; pp: pheap_mem_info;
size, ppsize: ptruint): boolean; inline;
var
i: ptruint;
- bp : pointer;
+ bp,pcaddr : pointer;
ptext : ^text;
{$ifdef EXTRA}
pp2 : pheap_mem_info;
@@ -612,12 +628,15 @@ begin
end
else
begin
- bp:=get_caller_frame(get_frame);
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
+
if (bp>=StackBottom) and (bp<(StackBottom + StackLength)) then
for i:=(tracesize div 2)+1 to tracesize do
begin
- pp^.calls[i]:=get_caller_addr(bp);
- bp:=get_caller_frame(bp);
+ get_caller_stackinfo(bp,pcaddr);
+ pp^.calls[i]:=pcaddr;
if not((bp>=StackBottom) and (bp<(StackBottom + StackLength))) then
break;
end;
@@ -775,7 +794,8 @@ var
movesize,
i : ptruint;
oldbp,
- bp : pointer;
+ bp,
+ pcaddr : pointer;
pl : pdword;
pp : pheap_mem_info;
oldsize,
@@ -890,13 +910,15 @@ begin
inc(loc_info^.getmem_size,size);
inc(loc_info^.getmem8_size,(size+7) and not 7);
{ generate new backtrace }
- bp:=get_caller_frame(get_frame);
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
if (bp>=StackBottom) and (bp<(StackBottom + StackLength)) then
for i:=1 to tracesize do
begin
- pp^.calls[i]:=get_caller_addr(bp);
oldbp:=bp;
- bp:=get_caller_frame(bp);
+ get_caller_stackinfo(bp,pcaddr);
+ pp^.calls[i]:=pcaddr;
if (bp<oldbp) or (bp>(StackBottom + StackLength)) then
break;
end;
@@ -979,6 +1001,7 @@ var
{$ifdef morphos}
stack_top: longword;
{$endif morphos}
+ bp,pcaddr : pointer;
ptext : ^text;
label
_exit;
@@ -1136,7 +1159,10 @@ begin
end;
end;
writeln(ptext^,'pointer $',hexstr(p),' does not point to valid memory block');
- dump_stack(ptext^,get_caller_frame(get_frame));
+ bp:=get_frame;
+ pcaddr:=get_pc_addr;
+ get_caller_stackinfo(bp,pcaddr);
+ dump_stack(ptext^,bp,pcaddr);
runerror(204);
_exit:
end;
diff --git a/mips/rtl/inc/system.inc b/mips/rtl/inc/system.inc
index 25d04d563b..47d5d97e95 100644
--- a/mips/rtl/inc/system.inc
+++ b/mips/rtl/inc/system.inc
@@ -78,6 +78,7 @@ Const
Procedure HandleError (Errno : Longint); forward;
Procedure HandleErrorFrame (Errno : longint;frame : Pointer); forward;
+Procedure HandleErrorAddrFrame (Errno : longint;addr,frame : Pointer); forward;
{$ifdef FPC_HAS_FEATURE_TEXTIO}
type
@@ -668,33 +669,60 @@ End;
Miscellaneous
*****************************************************************************}
+{$ifndef FPC_SYSTEM_HAS_GET_PC_ADDR}
+ { This provides a dummy implementation
+ of get_pc_addr function, for CPU's that don't need
+ the instruction address to walk the stack. }
+function get_pc_addr : pointer;
+begin
+ get_pc_addr:=nil;
+end;
+{$endif ndef FPC_SYSTEM_HAS_GET_PC_ADDR}
+
+{$ifndef FPC_SYSTEM_HAS_GET_CALLER_STACKINFO}
+ { This provides a simpel implementation
+ of get_caller_stackinfo procedure,
+ using get_caller_addr and get_caller_frame
+ functions. }
+procedure get_caller_stackinfo(var framebp,addr : pointer);
+var
+ nextbp,nextaddr : pointer;
+begin
+ nextbp:=get_caller_frame(framebp,addr);
+ nextaddr:=get_caller_addr(framebp,addr);
+ framebp:=nextbp;
+ addr:=nextaddr;
+end;
+{$endif ndef FPC_SYSTEM_HAS_GET_CALLER_STACKINFO}
+
+
procedure fpc_rangeerror;[public,alias:'FPC_RANGEERROR']; compilerproc;
begin
- HandleErrorFrame(201,get_frame);
+ HandleErrorAddrFrame(201,get_pc_addr,get_frame);
end;
procedure fpc_divbyzero;[public,alias:'FPC_DIVBYZERO']; compilerproc;
begin
- HandleErrorFrame(200,get_frame);
+ HandleErrorAddrFrame(200,get_pc_addr,get_frame);
end;
procedure fpc_overflow;[public,alias:'FPC_OVERFLOW']; compilerproc;
begin
- HandleErrorFrame(215,get_frame);
+ HandleErrorAddrFrame(215,get_pc_addr,get_frame);
end;
procedure fpc_threaderror; [public,alias:'FPC_THREADERROR'];
begin
- HandleErrorFrame(6,get_frame);
+ HandleErrorAddrFrame(6,get_pc_addr,get_frame);
end;
procedure fpc_invalidpointer; [public,alias:'FPC_INVALIDPOINTER'];
begin
- HandleErrorFrame(216,get_frame);
+ HandleErrorAddrFrame(216,get_pc_addr,get_frame);
end;
@@ -708,7 +736,7 @@ begin
begin
l:=HInOutRes^;
HInOutRes^:=0;
- HandleErrorFrame(l,get_frame);
+ HandleErrorAddrFrame(l,get_pc_addr,get_frame);
end;
end;
@@ -737,7 +765,7 @@ begin
begin
if assigned(SafeCallErrorProc) then
SafeCallErrorProc(res,get_frame);
- HandleErrorFrame(229,get_frame);
+ HandleErrorAddrFrame(229,get_pc_addr,get_frame);
end;
result:=res;
end;
@@ -1024,15 +1052,20 @@ Procedure HandleError (Errno : longint);[public,alias : 'FPC_HANDLEERROR'];
Internal function should ALWAYS call HandleError instead of RunError.
}
begin
- HandleErrorFrame(Errno,get_frame);
+ HandleErrorAddrFrame(Errno,get_pc_addr,get_frame);
end;
procedure RunError(w : word);[alias: 'FPC_RUNERROR'];
+var
+ bp,pcaddr : pointer;
begin
errorcode:=w;
- erroraddr:=get_caller_addr(get_frame);
- errorbase:=get_caller_frame(get_frame);
+ pcaddr:=get_pc_addr;
+ bp:=get_frame;
+ get_caller_stackinfo(bp,pcaddr);
+ erroraddr:=pcaddr;
+ errorbase:=bp;
Halt(errorcode);
end;
@@ -1055,10 +1088,11 @@ begin
end;
-Procedure dump_stack(var f : text;bp : Pointer);
+Procedure dump_stack(var f : text;bp,addr : Pointer);
var
i : Longint;
prevbp : Pointer;
+ prevaddr : pointer;
is_dev : boolean;
caller_frame,
caller_addr : Pointer;
@@ -1067,12 +1101,13 @@ Begin
try
{$endif FPC_HAS_FEATURE_EXCEPTIONS}
prevbp:=bp-1;
+ prevaddr:=nil;
i:=0;
is_dev:=do_isdevice(textrec(f).Handle);
while bp > prevbp Do
Begin
- caller_addr := get_caller_addr(bp);
- caller_frame := get_caller_frame(bp);
+ caller_addr := get_caller_addr(bp,addr);
+ caller_frame := get_caller_frame(bp,addr);
if (caller_addr=nil) then
break;
Writeln(f,BackTraceStrFunc(caller_addr));
@@ -1082,7 +1117,9 @@ Begin
If ((i>max_frame_dump) and is_dev) or (i>256) Then
break;
prevbp:=bp;
+ prevaddr:=addr;
bp:=caller_frame;
+ addr:=caller_addr;
End;
{$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
except
@@ -1268,16 +1305,17 @@ procedure fpc_AbstractErrorIntern;compilerproc;[public,alias : 'FPC_ABSTRACTERRO
begin
If pointer(AbstractErrorProc)<>nil then
AbstractErrorProc();
- HandleErrorFrame(211,get_frame);
+ HandleErrorAddrFrame(211,get_pc_addr,get_frame);
end;
-Procedure fpc_assert(Const Msg,FName:Shortstring;LineNo:Longint;ErrorAddr:Pointer); [Public,Alias : 'FPC_ASSERT']; compilerproc;
+Procedure fpc_assert(Const Msg,FName:Shortstring;LineNo:Longint;
+ ErrorAddr:Pointer); [Public,Alias : 'FPC_ASSERT']; compilerproc;
begin
if pointer(AssertErrorProc)<>nil then
AssertErrorProc(Msg,FName,LineNo,ErrorAddr)
else
- HandleErrorFrame(227,get_frame);
+ HandleErrorAddrFrame(227,get_pc_addr,get_frame);
end;
diff --git a/mips/rtl/inc/systemh.inc b/mips/rtl/inc/systemh.inc
index 511a4487a1..a4715dd2a9 100644
--- a/mips/rtl/inc/systemh.inc
+++ b/mips/rtl/inc/systemh.inc
@@ -644,7 +644,7 @@ Function Random: extended;
Procedure Randomize;
{$endif FPC_HAS_FEATURE_RANDOM}
-{$ifdef FPC_HAS_INTERNAL_ABS_LONG and (defined(cpui386) or defined(cpux86_64) or defined(cpupowerpc))}
+{$ifdef FPC_HAS_INTERNAL_ABS_LONG}
{$define FPC_SYSTEM_HAS_ABS_LONGINT}
Function abs(l:longint):longint;[internproc:fpc_in_abs_long];
{$else FPC_HAS_INTERNAL_ABS_LONG}
@@ -1059,15 +1059,18 @@ Procedure getdir(drivenr:byte;var dir:ansistring);
//function get_frame:pointer;[INTERNPROC:fpc_in_get_frame];
(*
// still defined externally
-function get_caller_addr(framebp:pointer):pointer;[INTERNPROC:fpc_in_get_caller_addr];
-function get_caller_frame(framebp:pointer):pointer;[INTERNPROC:fpc_in_get_caller_frame];
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;[INTERNPROC:fpc_in_get_caller_addr];
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;[INTERNPROC:fpc_in_get_caller_frame];
*)
{$ELSE}
function get_frame:pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
{$ENDIF}
-function get_caller_addr(framebp:pointer):pointer;
-function get_caller_frame(framebp:pointer):pointer;
+Function Get_pc_addr : Pointer;
+
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
+procedure get_caller_stackinfo(var framebp,addr : pointer);
Function IOResult:Word;
Function Sptr:Pointer;[internconst:fpc_in_const_ptr];
@@ -1149,7 +1152,7 @@ Function Paramcount:Longint;
Function ParamStr(l:Longint):string;
{$endif FPC_HAS_FEATURE_COMMANDARGS}
-Procedure Dump_Stack(var f : text;bp:pointer);
+Procedure Dump_Stack(var f : text;bp:pointer;addr : pointer = nil);
{$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
procedure DumpExceptionBackTrace(var f:text);
{$endif FPC_HAS_FEATURE_EXCEPTIONS}
diff --git a/mips/rtl/inc/variant.inc b/mips/rtl/inc/variant.inc
index 19cf9b4569..b41465346d 100644
--- a/mips/rtl/inc/variant.inc
+++ b/mips/rtl/inc/variant.inc
@@ -52,7 +52,7 @@ procedure fpc_variant_copy(var d: tvardata; const s : tvardata);[Public,Alias:'F
VarCopyProc(d,s);
end;
-procedure fpc_variant_copy_overwrite(const source: tvardata; var dest : tvardata);[Public,Alias:'FPC_VARIANT_COPY_OVERWRITE']; compilerproc;
+procedure fpc_variant_copy_overwrite(constref source: tvardata; var dest : tvardata);[Public,Alias:'FPC_VARIANT_COPY_OVERWRITE']; compilerproc;
begin
dest.VType := varEmpty;
if assigned(VarCopyProc) then
diff --git a/mips/rtl/java/jastringh.inc b/mips/rtl/java/jastringh.inc
index 2a4fcb0ea4..1570e13749 100644
--- a/mips/rtl/java/jastringh.inc
+++ b/mips/rtl/java/jastringh.inc
@@ -26,6 +26,7 @@ type
constructor Create(len: longint; cp: TSystemCodePage);overload;
constructor Create(const arr: array of ansichar; length: longint; cp: TSystemCodePage);overload;
constructor Create(const arr: array of unicodechar; cp: TSystemCodePage);overload;
+ constructor Create(const u: unicodestring);overload;
constructor Create(const u: unicodestring; cp: TSystemCodePage);overload;
constructor Create(const a: RawByteString; cp: TSystemCodePage);overload;
constructor Create(const s: shortstring; cp: TSystemCodePage);overload;
diff --git a/mips/rtl/java/jastrings.inc b/mips/rtl/java/jastrings.inc
index 6eccb4827f..276f7829ca 100644
--- a/mips/rtl/java/jastrings.inc
+++ b/mips/rtl/java/jastrings.inc
@@ -79,6 +79,13 @@ begin
end;
+constructor AnsistringClass.Create(const u: unicodestring);
+begin
+ { for use in Java code }
+ Create(u,DefaultSystemCodePage);
+end;
+
+
constructor AnsistringClass.Create(const a: RawByteString; cp: TSystemCodePage);
begin
Create(AnsistringClass(a).fdata,system.length(AnsistringClass(a).fdata)-1,cp);
diff --git a/mips/rtl/java/java_sysh.inc b/mips/rtl/java/java_sysh.inc
index 540e49f8a2..129399a09f 100644
--- a/mips/rtl/java/java_sysh.inc
+++ b/mips/rtl/java/java_sysh.inc
@@ -1,4 +1,27 @@
-{ Imports for Java packages/classes: java.io.IIOException, java.io.IOException, java.io.Serializable, java.lang.AbstractStringBuilder, java.lang.Appendable, java.lang.AssertionError, java.lang.Boolean, java.lang.Byte, java.lang.CharSequence, java.lang.Character, java.lang.Class, java.lang.Cloneable, java.lang.Comparable, java.lang.Double, java.lang.Enum, java.lang.Error, java.lang.Exception, java.lang.Float, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.IndexOutOfBoundsException, java.lang.Integer, java.lang.Iterable, java.lang.LinkageError, java.lang.Long, java.lang.Math, java.lang.NoSuchMethodException, java.lang.Number, java.lang.Object, java.lang.Readable, java.lang.Runtime, java.lang.RuntimeException, java.lang.Short, java.lang.String, java.lang.StringBuffer, java.lang.StringBuilder, java.lang.System, java.lang.ThreadLocal, java.lang.Throwable, java.lang.UnsupportedOperationException, java.lang.reflect.AccessibleObject, java.lang.reflect.AnnotatedElement, java.lang.reflect.Array, java.lang.reflect.Field, java.lang.reflect.GenericDeclaration, java.lang.reflect.InvocationTargetException, java.lang.reflect.Member, java.lang.reflect.Method, java.lang.reflect.Type, java.math.BigInteger, java.nio.Buffer, java.nio.ByteBuffer, java.nio.CharBuffer, java.nio.charset., java.text.Collator, java.util.AbstractCollection, java.util.AbstractMap, java.util.AbstractSet, java.util.Arrays, java.util.BitSet, java.util.Calendar, java.util.Collection, java.util.Comparator, java.util.EnumSet, java.util.HashMap, java.util.Iterator, java.util.Map, java.util.Set }
+{ Imports for Java packages/classes:
+ java.io.IIOException, java.io.IOException, java.io.Serializable,
+ java.lang.AbstractStringBuilder, java.lang.Appendable,
+ java.lang.AssertionError, java.lang.Boolean, java.lang.Byte,
+ java.lang.CharSequence, java.lang.Character, java.lang.Class,
+ java.lang.Cloneable, java.lang.Comparable, java.lang.Double,
+ java.lang.Enum, java.lang.Error, java.lang.Exception, java.lang.Float,
+ java.lang.IllegalArgumentException, java.lang.IllegalStateException,
+ java.lang.IndexOutOfBoundsException, java.lang.Integer, java.lang.Iterable,
+ java.lang.LinkageError, java.lang.Long, java.lang.Math,
+ java.lang.NoSuchMethodException, java.lang.Number, java.lang.Object,
+ java.lang.Readable, java.lang.Runtime, java.lang.RuntimeException,
+ java.lang.Short, java.lang.String, java.lang.StringBuffer,
+ java.lang.StringBuilder, java.lang.System, java.lang.ThreadLocal,
+ java.lang.Throwable, java.lang.UnsupportedOperationException,
+ java.lang.reflect.AccessibleObject, java.lang.reflect.AnnotatedElement,
+ java.lang.reflect.Array, java.lang.reflect.Field,
+ java.lang.reflect.GenericDeclaration, java.lang.reflect.InvocationTargetException,
+ java.lang.reflect.Member, java.lang.reflect.Method, java.lang.reflect.Type,
+ java.math.BigInteger, java.nio.Buffer, java.nio.ByteBuffer, java.nio.CharBuffer,
+ java.nio.charset., java.text.Collator, java.util.AbstractCollection,
+ java.util.AbstractMap, java.util.AbstractSet, java.util.Arrays, java.util.BitSet,
+ java.util.Calendar, java.util.Collection, java.util.Comparator, java.util.EnumSet,
+ java.util.HashMap, java.util.Iterator, java.util.Map, java.util.Set }
type
JLNoSuchMethodException = class;
Arr1JLNoSuchMethodException = array of JLNoSuchMethodException;
diff --git a/mips/rtl/java/jcompproc.inc b/mips/rtl/java/jcompproc.inc
index 49403c5655..68a9d8bb46 100644
--- a/mips/rtl/java/jcompproc.inc
+++ b/mips/rtl/java/jcompproc.inc
@@ -376,7 +376,7 @@ procedure fpc_variant_init(var v: tvardata);compilerproc;
procedure fpc_variant_clear(var v: tvardata);compilerproc;
{$ifdef FPC_VARIANTCOPY_FIXED}
procedure fpc_variant_copy(var d: tvardata; const s : tvardata);compilerproc;
-procedure fpc_variant_copy_overwrite(const source: tvardata; var dest : tvardata);compilerproc;
+procedure fpc_variant_copy_overwrite(constref source: tvardata; var dest : tvardata);compilerproc;
{$else FPC_VARIANTCOPY_FIXED}
procedure fpc_variant_copy(d,s : pointer);compilerproc;
procedure fpc_variant_copy_overwrite(source, dest : pointer);compilerproc;
diff --git a/mips/rtl/java/jsystemh.inc b/mips/rtl/java/jsystemh.inc
index 583e93b440..e21e2c6bc7 100644
--- a/mips/rtl/java/jsystemh.inc
+++ b/mips/rtl/java/jsystemh.inc
@@ -169,7 +169,7 @@ Function Random: extended;
Procedure Randomize;
{$endif FPC_HAS_FEATURE_RANDOM}
-{$ifdef FPC_HAS_INTERNAL_ABS_LONG and (defined(cpui386) or defined(cpux86_64) or defined(cpupowerpc))}
+{$ifdef FPC_HAS_INTERNAL_ABS_LONG}
{$define FPC_SYSTEM_HAS_ABS_LONGINT}
Function abs(l:longint):longint;[internproc:fpc_in_abs_long];
{$else FPC_HAS_INTERNAL_ABS_LONG}
@@ -591,15 +591,15 @@ Procedure getdir(drivenr:byte;var dir:ansistring);
//function get_frame:pointer;[INTERNPROC:fpc_in_get_frame];
(*
// still defined externally
-function get_caller_addr(framebp:pointer):pointer;[INTERNPROC:fpc_in_get_caller_addr];
-function get_caller_frame(framebp:pointer):pointer;[INTERNPROC:fpc_in_get_caller_frame];
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;[INTERNPROC:fpc_in_get_caller_addr];
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;[INTERNPROC:fpc_in_get_caller_frame];
*)
{$ELSE}
function get_frame:pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
{$ENDIF}
(*
-function get_caller_addr(framebp:pointer):pointer;
-function get_caller_frame(framebp:pointer):pointer;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
*)
//Function IOResult:Word;
diff --git a/mips/rtl/jvm/jvm.inc b/mips/rtl/jvm/jvm.inc
index 43b18fddd9..a588dc81e5 100644
--- a/mips/rtl/jvm/jvm.inc
+++ b/mips/rtl/jvm/jvm.inc
@@ -25,7 +25,7 @@ Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
begin
softfloat_exception_mask:=float_flag_underflow or float_flag_inexact or float_flag_denormal;
end;
-
+
{$define FPC_SYSTEM_HAS_SYSRESETFPU}
Procedure SysResetFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
begin
@@ -49,14 +49,14 @@ function get_frame:pointer;
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
begin
result:=nil;
end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
begin
result:=nil;
end;
diff --git a/mips/rtl/linux/Makefile b/mips/rtl/linux/Makefile
index eefecc7e17..ae78a02681 100644
--- a/mips/rtl/linux/Makefile
+++ b/mips/rtl/linux/Makefile
@@ -1,5 +1,5 @@
#
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/05/29]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/07/07]
#
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 powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd 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 powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux jvm-java jvm-android
@@ -3214,6 +3214,11 @@ strings$(PPUEXT) : $(INC)/strings.pp $(INC)/stringsi.inc\
unix$(PPUEXT) : $(UNIXINC)/unix.pp strings$(PPUEXT) baseunix$(PPUEXT) $(INC)/textrec.inc $(INC)/filerec.inc \
unxconst.inc $(UNIXINC)/timezone.inc $(SYSTEMUNIT)$(PPUEXT) \
unxfunc.inc
+ $(COMPILER) $(UNIXINC)/unix.pp
+syscall$(PPUEXT) : $(UNIXINC)/syscall.pp $(ARCH)/syscallh.inc $(ARCH)/sysnr.inc $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/syscall.pp
+unixutil$(PPUEXT) : $(UNIXINC)/unixutil.pp $(INC)/textrec.inc $(INC)/filerec.inc $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/unixutil.pp
unixtype$(PPUEXT) : $(UNIXINC)/unixtype.pp ptypes.inc $(UNIXINC)/ctypes.inc $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/unixtype.pp
baseunix$(PPUEXT) : errno.inc ptypes.inc $(UNIXINC)/ctypes.inc \
@@ -3221,7 +3226,9 @@ baseunix$(PPUEXT) : errno.inc ptypes.inc $(UNIXINC)/ctypes.inc \
bunxsysc.inc $(ARCH)/syscallh.inc $(ARCH)/sysnr.inc \
ostypes.inc osmacro.inc $(UNIXINC)/gensigset.inc \
$(UNIXINC)/genfuncs.inc $(SYSTEMUNIT)$(PPUEXT)
-ports$(PPUEXT) : ports.pp unix$(PPUEXT) objpas$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/baseunix.pp
+ports$(PPUEXT) : $(UNIXINC)/ports.pp unix$(PPUEXT) objpas$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/ports.pp
dl$(PPUEXT) : $(UNIXINC)/dl.pp $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/dl.pp
dynlibs$(PPUEXT) : $(INC)/dynlibs.pas $(UNIXINC)/dynlibs.inc dl$(PPUEXT) objpas$(PPUEXT)
@@ -3284,6 +3291,8 @@ cpu$(PPUEXT) : $(PROCINC)/cpu.pp $(SYSTEMUNIT)$(PPUEXT)
endif
mmx$(PPUEXT) : $(PROCINC)/mmx.pp cpu$(PPUEXT) $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(PROCINC)/mmx.pp
+x86$(PPUEXT) : $(UNIXINC)/x86.pp baseunix$(PPUEXT) syscall$(PPUEXT) $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/x86.pp
getopts$(PPUEXT) : $(INC)/getopts.pp $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(INC)/getopts.pp
heaptrc$(PPUEXT) : $(INC)/heaptrc.pp $(SYSTEMUNIT)$(PPUEXT)
diff --git a/mips/rtl/linux/Makefile.fpc b/mips/rtl/linux/Makefile.fpc
index 8f27da22e3..fcf56b0fe0 100644
--- a/mips/rtl/linux/Makefile.fpc
+++ b/mips/rtl/linux/Makefile.fpc
@@ -187,6 +187,13 @@ strings$(PPUEXT) : $(INC)/strings.pp $(INC)/stringsi.inc\
unix$(PPUEXT) : $(UNIXINC)/unix.pp strings$(PPUEXT) baseunix$(PPUEXT) $(INC)/textrec.inc $(INC)/filerec.inc \
unxconst.inc $(UNIXINC)/timezone.inc $(SYSTEMUNIT)$(PPUEXT) \
unxfunc.inc
+ $(COMPILER) $(UNIXINC)/unix.pp
+
+syscall$(PPUEXT) : $(UNIXINC)/syscall.pp $(ARCH)/syscallh.inc $(ARCH)/sysnr.inc $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/syscall.pp
+
+unixutil$(PPUEXT) : $(UNIXINC)/unixutil.pp $(INC)/textrec.inc $(INC)/filerec.inc $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/unixutil.pp
unixtype$(PPUEXT) : $(UNIXINC)/unixtype.pp ptypes.inc $(UNIXINC)/ctypes.inc $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/unixtype.pp
@@ -196,8 +203,10 @@ baseunix$(PPUEXT) : errno.inc ptypes.inc $(UNIXINC)/ctypes.inc \
bunxsysc.inc $(ARCH)/syscallh.inc $(ARCH)/sysnr.inc \
ostypes.inc osmacro.inc $(UNIXINC)/gensigset.inc \
$(UNIXINC)/genfuncs.inc $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/baseunix.pp
-ports$(PPUEXT) : ports.pp unix$(PPUEXT) objpas$(PPUEXT)
+ports$(PPUEXT) : $(UNIXINC)/ports.pp unix$(PPUEXT) objpas$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/ports.pp
dl$(PPUEXT) : $(UNIXINC)/dl.pp $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(UNIXINC)/dl.pp
@@ -303,6 +312,9 @@ endif
mmx$(PPUEXT) : $(PROCINC)/mmx.pp cpu$(PPUEXT) $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(PROCINC)/mmx.pp
+x86$(PPUEXT) : $(UNIXINC)/x86.pp baseunix$(PPUEXT) syscall$(PPUEXT) $(SYSTEMUNIT)$(PPUEXT)
+ $(COMPILER) $(UNIXINC)/x86.pp
+
getopts$(PPUEXT) : $(INC)/getopts.pp $(SYSTEMUNIT)$(PPUEXT)
$(COMPILER) $(INC)/getopts.pp
diff --git a/mips/rtl/linux/errno-mips.inc b/mips/rtl/linux/errno-mips.inc
new file mode 100644
index 0000000000..7d605ab465
--- /dev/null
+++ b/mips/rtl/linux/errno-mips.inc
@@ -0,0 +1,147 @@
+{ File generated by ../unix/scripts/check_errno.sh
+ generated on "Linux 2.6.27.1 mips64" machine
+List of missing system error number found in
+/usr/include/asm-generic/errno-base.h
+/usr/include/asm/errno.h
+/usr/include/bits/errno.h
+/usr/include/bits/wordsize.h
+/usr/include/errno.h
+/usr/include/features.h
+/usr/include/gnu/stubs.h
+/usr/include/linux/errno.h
+/usr/include/sys/cdefs.h
+}
+ ESysEPERM = 1; { Operation not permitted }
+ ESysENOENT = 2; { No such file or directory }
+ ESysESRCH = 3; { No such process }
+ ESysEINTR = 4; { Interrupted system call }
+ ESysEIO = 5; { I/O error }
+ ESysENXIO = 6; { No such device or address }
+ ESysE2BIG = 7; { Argument list too long }
+ ESysENOEXEC = 8; { Exec format error }
+ ESysEBADF = 9; { Bad file number }
+ ESysECHILD = 10; { No child processes }
+ ESysEAGAIN = 11; { Try again }
+ ESysENOMEM = 12; { Out of memory }
+ ESysEACCES = 13; { Permission denied }
+ ESysEFAULT = 14; { Bad address }
+ ESysENOTBLK = 15; { Block device required }
+ ESysEBUSY = 16; { Device or resource busy }
+ ESysEEXIST = 17; { File exists }
+ ESysEXDEV = 18; { Cross-device link }
+ ESysENODEV = 19; { No such device }
+ ESysENOTDIR = 20; { Not a directory }
+ ESysEISDIR = 21; { Is a directory }
+ ESysEINVAL = 22; { Invalid argument }
+ ESysENFILE = 23; { File table overflow }
+ ESysEMFILE = 24; { Too many open files }
+ ESysENOTTY = 25; { Not a typewriter }
+ ESysETXTBSY = 26; { Text file busy }
+ ESysEFBIG = 27; { File too large }
+ ESysENOSPC = 28; { No space left on device }
+ ESysESPIPE = 29; { Illegal seek }
+ ESysEROFS = 30; { Read-only file system }
+ ESysEMLINK = 31; { Too many links }
+ ESysEPIPE = 32; { Broken pipe }
+ ESysEDOM = 33; { Math argument out of domain of func }
+ ESysERANGE = 34; { Math result not representable }
+ ESysENOMSG = 35; { No message of desired type }
+ ESysEIDRM = 36; { Identifier removed }
+ ESysECHRNG = 37; { Channel number out of range }
+ ESysEL2NSYNC = 38; { Level 2 not synchronized }
+ ESysEL3HLT = 39; { Level 3 halted }
+ ESysEL3RST = 40; { Level 3 reset }
+ ESysELNRNG = 41; { Link number out of range }
+ ESysEUNATCH = 42; { Protocol driver not attached }
+ ESysENOCSI = 43; { No CSI structure available }
+ ESysEL2HLT = 44; { Level 2 halted }
+ ESysEDEADLK = 45; { Resource deadlock would occur }
+ ESysENOLCK = 46; { No record locks available }
+ ESysEBADE = 50; { Invalid exchange }
+ ESysEBADR = 51; { Invalid request descriptor }
+ ESysEXFULL = 52; { Exchange full }
+ ESysENOANO = 53; { No anode }
+ ESysEBADRQC = 54; { Invalid request code }
+ ESysEBADSLT = 55; { Invalid slot }
+ ESysEDEADLOCK = 56; { File locking deadlock error }
+ ESysEBFONT = 59; { Bad font file format }
+ ESysENOSTR = 60; { Device not a stream }
+ ESysENODATA = 61; { No data available }
+ ESysETIME = 62; { Timer expired }
+ ESysENOSR = 63; { Out of streams resources }
+ ESysENONET = 64; { Machine is not on the network }
+ ESysENOPKG = 65; { Package not installed }
+ ESysEREMOTE = 66; { Object is remote }
+ ESysENOLINK = 67; { Link has been severed }
+ ESysEADV = 68; { Advertise error }
+ ESysESRMNT = 69; { Srmount error }
+ ESysECOMM = 70; { Communication error on send }
+ ESysEPROTO = 71; { Protocol error }
+ ESysEDOTDOT = 73; { RFS specific error }
+ ESysEMULTIHOP = 74; { Multihop attempted }
+ ESysEBADMSG = 77; { Not a data message }
+ ESysENAMETOOLONG = 78; { File name too long }
+ ESysEOVERFLOW = 79; { Value too large for defined data type }
+ ESysENOTUNIQ = 80; { Name not unique on network }
+ ESysEBADFD = 81; { File descriptor in bad state }
+ ESysEREMCHG = 82; { Remote address changed }
+ ESysELIBACC = 83; { Can not access a needed shared library }
+ ESysELIBBAD = 84; { Accessing a corrupted shared library }
+ ESysELIBSCN = 85; { .lib section in a.out corrupted }
+ ESysELIBMAX = 86; { Attempting to link in too many shared libraries }
+ ESysELIBEXEC = 87; { Cannot exec a shared library directly }
+ ESysEILSEQ = 88; { Illegal byte sequence }
+ ESysENOSYS = 89; { Function not implemented }
+ ESysELOOP = 90; { Too many symbolic links encountered }
+ ESysERESTART = 91; { Interrupted system call should be restarted }
+ ESysESTRPIPE = 92; { Streams pipe error }
+ ESysENOTEMPTY = 93; { Directory not empty }
+ ESysEUSERS = 94; { Too many users }
+ ESysENOTSOCK = 95; { Socket operation on non-socket }
+ ESysEDESTADDRREQ = 96; { Destination address required }
+ ESysEMSGSIZE = 97; { Message too long }
+ ESysEPROTOTYPE = 98; { Protocol wrong type for socket }
+ ESysENOPROTOOPT = 99; { Protocol not available }
+ ESysEPROTONOSUPPORT = 120; { Protocol not supported }
+ ESysESOCKTNOSUPPORT = 121; { Socket type not supported }
+ ESysEOPNOTSUPP = 122; { Operation not supported on transport endpoint }
+ ESysEPFNOSUPPORT = 123; { Protocol family not supported }
+ ESysEAFNOSUPPORT = 124; { Address family not supported by protocol }
+ ESysEADDRINUSE = 125; { Address already in use }
+ ESysEADDRNOTAVAIL = 126; { Cannot assign requested address }
+ ESysENETDOWN = 127; { Network is down }
+ ESysENETUNREACH = 128; { Network is unreachable }
+ ESysENETRESET = 129; { Network dropped connection because of reset }
+ ESysECONNABORTED = 130; { Software caused connection abort }
+ ESysECONNRESET = 131; { Connection reset by peer }
+ ESysENOBUFS = 132; { No buffer space available }
+ ESysEISCONN = 133; { Transport endpoint is already connected }
+ ESysENOTCONN = 134; { Transport endpoint is not connected }
+ ESysEUCLEAN = 135; { Structure needs cleaning }
+ ESysENOTNAM = 137; { Not a XENIX named type file }
+ ESysENAVAIL = 138; { No XENIX semaphores available }
+ ESysEISNAM = 139; { Is a named type file }
+ ESysEREMOTEIO = 140; { Remote I/O error }
+ ESysEINIT = 141; { Reserved }
+ ESysEREMDEV = 142; { Error 142 }
+ ESysESHUTDOWN = 143; { Cannot send after transport endpoint shutdown }
+ ESysETOOMANYREFS = 144; { Too many references: cannot splice }
+ ESysETIMEDOUT = 145; { Connection timed out }
+ ESysECONNREFUSED = 146; { Connection refused }
+ ESysEHOSTDOWN = 147; { Host is down }
+ ESysEHOSTUNREACH = 148; { No route to host }
+ ESysEWOULDBLOCK = EsysEAGAIN; { Operation would block }
+ ESysEALREADY = 149; { Operation already in progress }
+ ESysEINPROGRESS = 150; { Operation now in progress }
+ ESysESTALE = 151; { Stale NFS file handle }
+ ESysECANCELED = 158; { AIO operation canceled }
+ ESysENOMEDIUM = 159; { No medium found }
+ ESysEMEDIUMTYPE = 160; { Wrong medium type }
+ ESysENOKEY = 161; { Required key not available }
+ ESysEKEYEXPIRED = 162; { Key has expired }
+ ESysEKEYREVOKED = 163; { Key has been revoked }
+ ESysEKEYREJECTED = 164; { Key was rejected by service }
+ ESysEOWNERDEAD = 165; { Owner died }
+ ESysENOTRECOVERABLE = 166; { State not recoverable }
+ ESysERFKILL = 167; { Operation not possible due to RF-kill }
+ ESysEDQUOT = 1133; { Quota exceeded }
diff --git a/mips/rtl/linux/errno.inc b/mips/rtl/linux/errno.inc
index 21819b9dd4..f1ccf4b5b4 100644
--- a/mips/rtl/linux/errno.inc
+++ b/mips/rtl/linux/errno.inc
@@ -24,6 +24,11 @@ const
{$i errno-sparc.inc}
{$endif CPUSPARC}
+{$ifdef CPUMIPS}
+{$define FPC_HAS_ESYS}
+{$i errno-mips.inc}
+{$endif CPUMIPS}
+
{$ifndef FPC_HAS_ESYS}
ESysEPERM = 1; { Operation not permitted }
ESysENOENT = 2; { No such file or directory }
diff --git a/mips/rtl/linux/mips/cprt0.as b/mips/rtl/linux/mips/cprt0.as
index e69de29bb2..2d9902569f 100644
--- a/mips/rtl/linux/mips/cprt0.as
+++ b/mips/rtl/linux/mips/cprt0.as
@@ -0,0 +1,149 @@
+/* Startup code compliant to the ELF Mips ABI.
+ Copyright (C) 1995, 1997, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment. The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
+ point runs, most registers' values are unspecified, except for:
+
+ v0 ($2) Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ sp ($29) The stack contains the arguments and environment:
+ 0(%esp) argc
+ 4(%esp) argv[0]
+ ...
+ (4*argc)(%esp) NULL
+ (4*(argc+1))(%esp) envp[0]
+ ...
+ NULL
+ ra ($31) The return address register is set to zero so that programs
+ that search backword through stack frames recognize the last
+ stack frame.
+*/
+
+
+/* We need to call:
+ __libc_start_main (int (*main) (int, char **, char **), int argc,
+ char **argv, void (*init) (void), void (*fini) (void),
+ void (*rtld_fini) (void), void *stack_end)
+*/
+ .text
+ .globl __start
+ .type __start,@function
+__start:
+.globl _start
+ .type _start,@function
+_start:
+ .ent _start
+
+
+ .set noreorder
+ move $0, $31
+ bal 10f
+ nop
+ 10:
+ .cpload $31
+ move $31, $0
+ .set reorder
+ /* Setup GP correctly if we're non-PIC. */
+ la $28,_gp
+
+ la $4, main /* main */
+ lw $5, 0($29) /* argc */
+ addiu $6, $29, 4 /* argv */
+ /* store argc */
+ lw $t0,0($29)
+ lui $t1,%hi(operatingsystem_parameter_argc)
+ sw $t0,%lo(operatingsystem_parameter_argc)($t1)
+
+ /* store argv */
+ addiu $t1,$29,4
+ lui $t2,%hi(operatingsystem_parameter_argv)
+ sw $t1,%lo(operatingsystem_parameter_argv)($t2)
+
+ /* store envp */
+ addiu $t2,$t0,1
+ sll $t2,$t2,0x2
+ addu $t2,$t2,$t1
+ lui $t3,%hi(operatingsystem_parameter_envp)
+ sw $t2,%lo(operatingsystem_parameter_envp)($t3)
+
+ /* Allocate space on the stack for seven arguments (o32 only)
+ and make sure the stack is aligned to double words (8 bytes)
+ on o32 and quad words (16 bytes) on n32 and n64. */
+ and $29, -2 * 4
+ subu $29, 32
+
+ lw $7,%got(__libc_csu_init)($gp) /* init */
+ lw $8,%got(__libc_csu_fini)($gp) /* fini */
+
+ sw $8, 16($29) /* fini */
+ sw $2, 20($29) /* rtld_fini */
+ sw $29, 24($29) /* stack_end */
+
+ lw $t9,%got(__libc_start_main)($gp)
+ jalr $t9
+ .end _start
+ .size _start, . - _start
+/* Crash if somehow it does return. */
+ .globl _haltproc
+ .ent _haltproc
+ .type _haltproc,@function
+_haltproc:
+hlt:
+ li $v0,4001
+ syscall
+ b hlt
+ .end _haltproc
+
+/* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
+
+ .comm __stkptr,4
+ .comm __dl_fini,4
+
+ .comm operatingsystem_parameter_envp,4
+ .comm operatingsystem_parameter_argc,4
+ .comm operatingsystem_parameter_argv,4
+
diff --git a/mips/rtl/linux/mips/dllprt0.as b/mips/rtl/linux/mips/dllprt0.as
index e69de29bb2..c6db79ac33 100644
--- a/mips/rtl/linux/mips/dllprt0.as
+++ b/mips/rtl/linux/mips/dllprt0.as
@@ -0,0 +1 @@
+.include "mips/prt0.as"
diff --git a/mips/rtl/linux/mips/gprt0.as b/mips/rtl/linux/mips/gprt0.as
index e69de29bb2..c6db79ac33 100644
--- a/mips/rtl/linux/mips/gprt0.as
+++ b/mips/rtl/linux/mips/gprt0.as
@@ -0,0 +1 @@
+.include "mips/prt0.as"
diff --git a/mips/rtl/linux/mips/prt0.as b/mips/rtl/linux/mips/prt0.as
index 88fc6e28c7..0bd2c63333 100644
--- a/mips/rtl/linux/mips/prt0.as
+++ b/mips/rtl/linux/mips/prt0.as
@@ -27,7 +27,7 @@ _dynamic_start:
nop
.end _dynamic_start
- .size _dynamic_start, .-_start
+ .size _dynamic_start, .-_dynamic_start
.align 4
.global _start
@@ -54,6 +54,8 @@ _dynamic_start:
_start:
/* load fp */
move $s8,$sp
+ lui $at,%hi(__stkptr)
+ sw $s8,%lo(__stkptr)($at)
/* align stack */
li $at,-8
@@ -82,8 +84,10 @@ _start:
sll $a2,$a2,0x2
addu $a2,$a2,$a1
lui $a3,%hi(operatingsystem_parameter_envp)
- jal PASCALMAIN
sw $a2,%lo(operatingsystem_parameter_envp)($a3)
+ lui $t9,%hi(PASCALMAIN)
+ addiu $t9,$t9,%lo(PASCALMAIN)
+ jalr $t9
nop
b _haltproc
nop
diff --git a/mips/rtl/linux/mips/sighnd.inc b/mips/rtl/linux/mips/sighnd.inc
index ae71d813c4..2a782e21f1 100644
--- a/mips/rtl/linux/mips/sighnd.inc
+++ b/mips/rtl/linux/mips/sighnd.inc
@@ -15,10 +15,11 @@
**********************************************************************}
-procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl;
+procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; UContext: PUContext);cdecl;
var
res : word;
addr : pointer;
+ frame : pointer;
begin
res:=0;
addr:=nil;
@@ -27,11 +28,12 @@ begin
begin
addr := siginfo^._sifields._sigfault._addr;
res := 207;
+
case siginfo^.si_code of
FPE_INTDIV:
res:=200;
FPE_INTOVF:
- res:=205;
+ res:=215;
FPE_FLTDIV:
res:=200;
FPE_FLTOVF:
@@ -57,5 +59,32 @@ begin
reenable_signal(sig);
{ give runtime error at the position where the signal was raised }
if res<>0 then
- HandleErrorAddrFrame(res,addr,nil);
+ begin
+ if assigned(UContext) then
+ begin
+ frame:=pointer(ptruint(UContext^.uc_mcontext.sigc_regs[29])); { stack pointer }
+ addr:=pointer(ptruint(UContext^.uc_mcontext.sigc_pc)); { program counter }
+ if sig=SIGFPE then
+ begin
+ { Clear FPU exception bits }
+ UContext^.uc_mcontext.sigc_fpc_csr := UContext^.uc_mcontext.sigc_fpc_csr
+ and not (fpu_cause_mask or fpu_flags_mask);
+ end;
+ { Change $a1, $a2, $a3 and sig_pc to HandleErrorAddrFrame parameters }
+ UContext^.uc_mcontext.sigc_regs[4]:=res;
+ UContext^.uc_mcontext.sigc_regs[5]:=ptrint(addr);
+ UContext^.uc_mcontext.sigc_regs[6]:=ptrint(frame);
+ UContext^.uc_mcontext.sigc_pc:=ptrint(@HandleErrorAddrFrame);
+ { Let the system call HandleErrorAddrFrame }
+ exit;
+ end
+ else
+ begin
+ frame:=nil;
+ addr:=nil;
+ end;
+ if sig=SIGFPE then
+ set_fsr(get_fsr and not (fpu_cause_mask or fpu_flags_mask));
+ HandleErrorAddrFrame(res,addr,frame);
+ end;
end;
diff --git a/mips/rtl/linux/mips/sighndh.inc b/mips/rtl/linux/mips/sighndh.inc
index e3cfd870f3..ce4ffdee67 100644
--- a/mips/rtl/linux/mips/sighndh.inc
+++ b/mips/rtl/linux/mips/sighndh.inc
@@ -25,22 +25,72 @@ type
ins : array[0..7] of longint;
end;
+(* MIPS OABI32 structure
+struct sigcontext {
+ unsigned int sc_regmask;
+ unsigned int sc_status;
+ unsigned long long sc_pc;
+ unsigned long long sc_regs[32];
+ unsigned long long sc_fpregs[32];
+ unsigned int sc_ownedfp;
+ unsigned int sc_fpc_csr;
+ unsigned int sc_fpc_eir;
+ unsigned int sc_used_math;
+ unsigned int sc_dsp;
+ unsigned long long sc_mdhi;
+ unsigned long long sc_mdlo;
+ unsigned long sc_hi1;
+ unsigned long sc_lo1;
+ unsigned long sc_hi2;
+ unsigned long sc_lo2;
+ unsigned long sc_hi3;
+ unsigned long sc_lo3;
+};
+typedef struct ucontext
+ {
+ unsigned long int uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ __sigset_t uc_sigmask;
+ } ucontext_t;
+
+ *)
+ FPReg = record
+ case byte of
+ 0 : (fp_dreg : double;);
+ 1 : (fp_reg : single;
+ fp_pad : cint; );
+ end;
+
PSigContext = ^TSigContext;
TSigContext = record
- sigc_onstack, { state to restore }
- sigc_mask, { sigmask to restore }
- sigc_sp, { stack pointer }
- sigc_pc, { program counter }
- sigc_npc, { next program counter }
- sigc_psr, { for condition codes etc }
- sigc_g1, { User uses these two registers }
- sigc_o0, { within the trampoline code. }
- { Now comes information regarding the users window set
- * at the time of the signal. }
- sigc_oswins : longint; { outstanding windows }
- { stack ptrs for each regwin buf }
- sigc_spbuf : array[0..__SUNOS_MAXWIN-1] of pchar;
- { Windows to restore after signal }
- sigc_wbuf : array[0..__SUNOS_MAXWIN] of twbuf;
+ sigc_regmask,
+ sigc_status: cuint;
+ sigc_pc : culonglong;
+ sigc_regs : array[0..31] of culonglong;
+ sigc_fpregs : array[0..31] of fpreg;
+ sigc_fpc_csr, sigc_fpc_eir : cuint;
+ sigc_used_math : cuint;
+ sigc_dsp : cuint;
+ sigc_mdhi, sigc_mdlo : culonglong;
+ sigc_hi1,sigc_lo1,
+ sigc_hi2,sigc_lo2,
+ sigc_hi3,sigc_lo3 : culong;
+ end;
+
+ TStack = record
+ ss_sp : pointer;
+ ss_size : size_t;
+ ss_flags : cint;
+ end;
+
+ PUContext = ^TUContext;
+ TUContext = record
+ uc_flags : culong;
+ uc_link : PUContext;
+ uc_stack : TStack;
+ uc_mcontext : TSigContext;
+ uc_sigmask : TSigSet;
end;
diff --git a/mips/rtl/linux/mips/syscall.inc b/mips/rtl/linux/mips/syscall.inc
index 677a20a93a..bc8c1bacce 100644
--- a/mips/rtl/linux/mips/syscall.inc
+++ b/mips/rtl/linux/mips/syscall.inc
@@ -47,7 +47,7 @@ asm
addiu $4,$4,%lo(errno)
jalr $8
nop
- lw $8,-4($fp)
+ lw $8,temp
sw $8,0($2)
.LFailed:
li $2,-1
@@ -225,7 +225,7 @@ asm
move $a0,$a1
move $a1,$a2
move $a2,$a3
- lw $a3,16($fp)
+ lw $a3,param4
syscall
nop
beq $7,$0,.LDone
@@ -266,10 +266,10 @@ asm
move $a0,$a1
move $a1,$a2
move $a2,$a3
- lw $a3,16($fp)
- lw $t0,20($fp)
+ lw $a3,param4
+ lw $t0,param5
sw $t0,16($sp)
-
+
syscall
nop
beq $7,$0,.LDone
@@ -311,10 +311,10 @@ asm
move $a0,$a1
move $a1,$a2
move $a2,$a3
- lw $a3,16($fp)
- lw $t0,20($fp)
+ lw $a3,param4
+ lw $t0,param5
sw $t0,16($sp)
- lw $t0,24($fp)
+ lw $t0,param6
sw $t0,20($sp)
syscall
nop
diff --git a/mips/rtl/linux/ossysc.inc b/mips/rtl/linux/ossysc.inc
index f7040b7aa5..2ff2825b35 100644
--- a/mips/rtl/linux/ossysc.inc
+++ b/mips/rtl/linux/ossysc.inc
@@ -319,7 +319,14 @@ begin
end;
end;
{$endif}
- Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(new_action),TSysParam(old_action),TSysParam(8));
+ Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),
+ TSysParam(new_action),TSysParam(old_action),
+ {$ifdef cpumips}
+ TSysParam(16{should be wordsinsigset})
+ {$else not cpumips}
+ TSysParam(8)
+ {$endif not cpumips}
+ );
{$endif cpusparc}
end;
@@ -569,7 +576,14 @@ function FPSigProcMask(how:cint;nset : psigset;oset : psigset):cint; [public, al
}
begin
- FPsigprocmask:=do_syscall(syscall_nr_rt_sigprocmask,TSysParam(how),TSysParam(nset),TSysParam(oset),TSysParam(8));
+ FPsigprocmask:=do_syscall(syscall_nr_rt_sigprocmask,TSysParam(how),
+ TSysParam(nset),TSysParam(oset),
+{$ifdef CPUMIPS}
+ TSysParam(16)
+{$else not CPUMIPS}
+ TSysParam(8)
+{$endif not CPUMIPS}
+ );
end;
Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
diff --git a/mips/rtl/linux/ostypes.inc b/mips/rtl/linux/ostypes.inc
index a0bcfa919b..b29a618a72 100644
--- a/mips/rtl/linux/ostypes.inc
+++ b/mips/rtl/linux/ostypes.inc
@@ -245,7 +245,20 @@ CONST
O_DIRECTORY = $10000;
O_NOFOLLOW = $20000;
O_DIRECT = $100000;
-{$else cpusparc}
+{$else : not cpusparc}
+{$ifdef cpumips}
+ O_CREAT = $100;
+ O_EXCL = $400;
+ O_NOCTTY = $800;
+ O_TRUNC = $200;
+ O_APPEND = $8;
+ O_NONBLOCK = $80;
+ O_NDELAY = O_NONBLOCK;
+ O_SYNC = $10;
+ O_DIRECT = $8000;
+ O_DIRECTORY = $10000;
+ O_NOFOLLOW = $20000;
+{$else : not cpumips}
O_CREAT = $40;
O_EXCL = $80;
O_NOCTTY = $100;
@@ -257,7 +270,8 @@ CONST
O_DIRECT = $4000;
O_DIRECTORY = $10000;
O_NOFOLLOW = $20000;
-{$endif cpusparc}
+{$endif not cpumips}
+{$endif not cpusparc}
{$if defined(cpuarm) or defined(cpualpha) or defined(cpublackfin) or defined(cpum68k)}
O_LARGEFILE = $20000;
diff --git a/mips/rtl/linux/ptypes.inc b/mips/rtl/linux/ptypes.inc
index a483ed5cf8..14e6c181b6 100644
--- a/mips/rtl/linux/ptypes.inc
+++ b/mips/rtl/linux/ptypes.inc
@@ -21,7 +21,7 @@
{ Introduced defines
- fs32bit, should be on if libc only supports sizeof(off_t)=4
- we assume one typically compiles C applications with
+ we assume one typically compiles C applications with
#define _FILE_OFFSET_BITS 64
All three tested systems (PPC,Alpha,2x i386) gave the same POSIX limits,
@@ -30,6 +30,33 @@ and all three 32-bit systems returned completely identical types too
introduction)
}
+{$ifdef CPUMIPS}
+{$define USE_PTHREAD_SIZEOF}
+{$ifdef CPU64}
+const
+ __SIZEOF_PTHREAD_ATTR_T = 56;
+ __SIZEOF_PTHREAD_MUTEX_T = 40;
+ __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
+ __SIZEOF_PTHREAD_COND_T = 48;
+ __SIZEOF_PTHREAD_CONDATTR_T = 4;
+ __SIZEOF_PTHREAD_RWLOCK_T = 56;
+ __SIZEOF_PTHREAD_RWLOCKATTR_T = 8;
+ __SIZEOF_PTHREAD_BARRIER_T = 32;
+ __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
+{$else : not CPU64, i.e. CPU32}
+const
+ __SIZEOF_PTHREAD_ATTR_T = 36;
+ __SIZEOF_PTHREAD_MUTEX_T = 24;
+ __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
+ __SIZEOF_PTHREAD_COND_T = 48;
+ __SIZEOF_PTHREAD_CONDATTR_T = 4;
+ __SIZEOF_PTHREAD_RWLOCK_T = 32;
+ __SIZEOF_PTHREAD_RWLOCKATTR_T = 8;
+ __SIZEOF_PTHREAD_BARRIER_T = 20;
+ __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
+{$endif CPU32}
+{$endif MIPS}
+
{$I ctypes.inc}
{$packrecords c}
@@ -119,7 +146,7 @@ Type
pUid = ^uid_t;
TGid = gid_t;
pGid = ^gid_t;
-
+
TIOCtlRequest = cInt;
@@ -177,7 +204,7 @@ Type
0: (__wch: wint_t);
1: (__wchb: array[0..3] of char);
end;
-
+
mbstate_t = record
__count: cint;
__value: mbstate_value_t;
@@ -190,7 +217,26 @@ Type
__sched_priority: cint;
end;
+ { MIPS32 size of unions
+ __SIZEOF_PTHREAD_ATTR_T = 36;
+ __SIZEOF_PTHREAD_MUTEX_T = 24;
+ __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
+ __SIZEOF_PTHREAD_COND_T = 48;
+ __SIZEOF_PTHREAD_CONDATTR_T = 4;
+ __SIZEOF_PTHREAD_RWLOCK_T = 32;
+ __SIZEOF_PTHREAD_RWLOCKATTR_T = 8;
+ __SIZEOF_PTHREAD_BARRIER_T = 20;
+ __SIZEOF_PTHREAD_BARRIERATTR_T = 4; }
+
pthread_attr_t = record
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_ATTR_T-1] of char;
+ __align : clong;
+ );
+ 1 : (
+ {$endif}
__detachstate: cint;
__schedpolicy: cint;
__schedparam: sched_param;
@@ -200,6 +246,9 @@ Type
__stackaddr_set: cint;
__stackaddr: pointer;
__stacksize: size_t;
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
_pthread_fastlock = record
@@ -208,26 +257,70 @@ Type
end;
pthread_mutex_t = record
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_MUTEX_T-1] of char;
+ __align : clong;
+ );
+ 1 : (
+ {$endif}
__m_reserved: cint;
__m_count: cint;
__m_owner: pointer;
__m_kind: cint;
__m_lock: _pthread_fastlock;
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
pthread_mutexattr_t = record
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_MUTEXATTR_T-1] of char;
+ __align : clong;
+ );
+ 1 : (
+ {$endif}
__mutexkind: cint;
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
pthread_cond_t = record
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_COND_T-1] of char;
+ ___align : clong;
+ );
+ 1 : (
+ {$endif}
__c_lock: _pthread_fastlock;
__c_waiting: pointer;
__padding: array[0..48-1-sizeof(_pthread_fastlock)-sizeof(pointer)-sizeof(clonglong)] of byte;
__align: clonglong;
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
pthread_condattr_t = record
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_CONDATTR_T-1] of char;
+ __align : clong;
+ );
+ 1 : (
+ {$endif}
__dummy: cint;
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
pthread_key_t = cuint;
@@ -235,16 +328,38 @@ Type
const
pthreadrwlocksize = {$ifdef CPU64} 56{$else}32{$endif};
-type
+type
pthread_rwlock_t = record // should be 56 for 64-bit, 32 bytes for 32-bit mantis #21552
- case boolean of
- false : (_data : array[0..pthreadrwlocksize-1] of char);
- true : (align : clong);
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_RWLOCK_T-1] of char;
+ __align : clong;
+ );
+ 1 : (
+ {$endif}
+ case boolean of
+ false : (_data : array[0..pthreadrwlocksize-1] of char);
+ true : (align : clong);
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
pthread_rwlockattr_t = record
+ {$ifdef USE_PTHREAD_SIZEOF}
+ case byte of
+ 0 : (
+ __size : array[0..__SIZEOF_PTHREAD_RWLOCKATTR_T-1] of char;
+ __align : clong;
+ );
+ 1 : (
+ {$endif}
__lockkind: cint;
__pshared: cint;
+ {$ifdef USE_PTHREAD_SIZEOF}
+ );
+ {$endif}
end;
sem_t = record
@@ -278,7 +393,11 @@ CONST
{$ifdef FPC_USE_LIBC}
SIG_MAXSIG = 1024; // highest signal version
{$else}
+ {$ifdef cpumips}
+ SIG_MAXSIG = 1024; // highest signal version
+ {$else not cupmips}
SIG_MAXSIG = 128; // highest signal version
+ {$endif not cpumips}
{$endif}
{ For getting/setting priority }
diff --git a/mips/rtl/linux/signal.inc b/mips/rtl/linux/signal.inc
index f4d92a6ce3..dbd4f3d7da 100644
--- a/mips/rtl/linux/signal.inc
+++ b/mips/rtl/linux/signal.inc
@@ -28,14 +28,20 @@ Const
SIG_UNBLOCK = 2;
SIG_SETMASK = 4;
{$else CPUSPARC}
-{$if defined(cpumips) or defined(cpumipsel)}
+{$ifdef CPUMIPS}
SA_NOCLDSTOP = 1;
SA_NOCLDWAIT = $10000;
SA_SIGINFO = 8;
+ SIG_BLOCK = 1;
+ SIG_UNBLOCK = 2;
+ SIG_SETMASK = 3;
{$else CPUMIPS}
SA_NOCLDSTOP = 1;
SA_NOCLDWAIT = 2;
SA_SIGINFO = 4;
+ SIG_BLOCK = 0;
+ SIG_UNBLOCK = 1;
+ SIG_SETMASK = 2;
{$endif CPUMIPS}
SA_RESTORER = $04000000;
SA_ONSTACK = $08000000;
@@ -47,16 +53,13 @@ Const
SA_NOMASK = SA_NODEFER;
SA_ONESHOT = SA_RESETHAND;
- SIG_BLOCK = 0;
- SIG_UNBLOCK = 1;
- SIG_SETMASK = 2;
{$endif CPUSPARC}
SIG_DFL = 0 ;
SIG_IGN = 1 ;
SIG_ERR = -1 ;
-{$ifdef cpusparc}
+{$ifdef CPUSPARC}
SIGHUP = 1;
SIGINT = 2;
SIGQUIT = 3;
@@ -99,15 +102,37 @@ Const
SIGTRAP = 5;
SIGABRT = 6;
SIGIOT = 6;
- SIGBUS = 7;
SIGFPE = 8;
SIGKILL = 9;
- SIGUSR1 = 10;
SIGSEGV = 11;
- SIGUSR2 = 12;
SIGPIPE = 13;
SIGALRM = 14;
- SIGTerm = 15;
+ SIGTERM = 15;
+{$ifdef CPUMIPS}
+ SIGEMT = 7;
+ SIGBUS = 10;
+ SIGSYS = 12;
+ SIGUSR1 = 16;
+ SIGUSR2 = 17;
+ SIGCHLD = 18;
+ SIGPWR = 19;
+ SIGWINCH = 20;
+ SIGURG = 21;
+ SIGIO = 22;
+ SIGPOLL = 22;
+ SIGSTOP = 23;
+ SIGTSTP = 24;
+ SIGCONT = 25;
+ SIGTTIN = 26;
+ SIGTTOU = 27;
+ SIGVTALRM = 28;
+ SIGPROF = 29;
+ SIGXCPU = 30;
+ SIGXFSZ = 31;
+{$else not CPUMIPS}
+ SIGBUS = 7;
+ SIGUSR1 = 10;
+ SIGUSR2 = 12;
SIGSTKFLT = 16;
SIGCHLD = 17;
SIGCONT = 18;
@@ -125,6 +150,7 @@ Const
SIGPOLL = SIGIO;
SIGPWR = 30;
SIGUNUSED = 31;
+{$endif not CPUMIPS}
{$endif cpusparc}
{ si_code field values for tsiginfo.si_code when si_signo = SIGFPE }
@@ -150,8 +176,13 @@ type
psiginfo = ^tsiginfo;
tsiginfo = record
si_signo : longint;
+{$ifdef CPUMIPS}
+ si_code : longint;
+ si_errno : longint;
+{$else not CPUMIPS}
si_errno : longint;
si_code : longint;
+{$endif not CPUMIPS}
_sifields : record
case longint of
0 : ( _pad : array[0..(SI_PAD_SIZE)-1] of longint );
@@ -210,10 +241,20 @@ type
sa_restorer: sigrestorerhandler_t;
end;
{$else}
+ {$ifdef cpumips}
+ sigactionrec = record
+ sa_flags: cuint;
+ sa_handler: sigactionhandler_t;
+ sa_mask: sigset_t;
+ sa_restorer: sigrestorerhandler_t; { Doesn't seem to exist on MIPS }
+ sa_resv : array [0..0] of cint;
+ end;
+ {$else not mips}
sigactionrec = record
sa_handler: sigactionhandler_t;
sa_flags: culong;
sa_restorer: sigrestorerhandler_t;
sa_mask: sigset_t;
end;
+ {$endif not mips}
{$endif}
diff --git a/mips/rtl/linux/sparc/sighnd.inc b/mips/rtl/linux/sparc/sighnd.inc
index cfbfc35149..5182920cfe 100644
--- a/mips/rtl/linux/sparc/sighnd.inc
+++ b/mips/rtl/linux/sparc/sighnd.inc
@@ -30,7 +30,7 @@ begin
FPE_INTDIV:
res:=200;
FPE_INTOVF:
- res:=205;
+ res:=215;
FPE_FLTDIV:
res:=200;
FPE_FLTOVF:
diff --git a/mips/rtl/linux/unxsockh.inc b/mips/rtl/linux/unxsockh.inc
index d85ad09b4c..ccbad9a18d 100644
--- a/mips/rtl/linux/unxsockh.inc
+++ b/mips/rtl/linux/unxsockh.inc
@@ -170,10 +170,10 @@ Const
IPPROTO_RAW = 255; { Raw IP packets. }
IPPROTO_MAX = 255;
//from /usr/include/bits/in.h
-{{ Options for use with etsockopt' and etsockopt' at the IP level.
+{ Options for use with getsockopt' and setsockopt' at the IP level.
The first word in the comment at the right is the data type used;
- "bool" means a boolean value stored in an nt'. }
-}
+ "bool" means a boolean value stored in an int'. }
+
IP_OPTIONS = 4; { ip_opts; IP per-packet options. }
IP_HDRINCL = 3; { int; Header is included with data. }
IP_TOS = 1; { int; IP type of service and precedence. }
@@ -227,9 +227,9 @@ Const
IP_MAX_MEMBERSHIPS = 20;
-{ Options for use with etsockopt' and etsockopt' at the IPv6 level.
+{ Options for use with getsockopt' and setsockopt' at the IPv6 level.
The first word in the comment at the right is the data type used;
- "bool" means a boolean value stored in an nt'. }
+ "bool" means a boolean value stored in an int'. }
IPV6_ADDRFORM = 1;
IPV6_PKTINFO = 2;
IPV6_HOPOPTS = 3;
diff --git a/mips/rtl/linux/x86_64/dllprt0.as b/mips/rtl/linux/x86_64/dllprt0.as
index 477da7785b..c86bbfd0c6 100644
--- a/mips/rtl/linux/x86_64/dllprt0.as
+++ b/mips/rtl/linux/x86_64/dllprt0.as
@@ -41,8 +41,8 @@ FPC_SHARED_LIB_START:
jmp _startlib@PLT
.text
- .globl _start
- .type _start,@function
+ .globl _startlib
+ .type _startlib,@function
_startlib:
pushq %rbx
movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rbx
diff --git a/mips/rtl/m68k/m68k.inc b/mips/rtl/m68k/m68k.inc
index 56636eacc0..d007587ab5 100644
--- a/mips/rtl/m68k/m68k.inc
+++ b/mips/rtl/m68k/m68k.inc
@@ -41,7 +41,7 @@ function get_frame : pointer; assembler;
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp : pointer) : pointer;
+function get_caller_addr(framebp : pointer;addr:pointer=nil) : pointer;
begin
asm
move.l framebp,a0
@@ -55,7 +55,7 @@ function get_caller_addr(framebp : pointer) : pointer;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp : pointer) : pointer;
+function get_caller_frame(framebp : pointer;addr:pointer=nil) : pointer;
begin
asm
move.l FRAMEBP,a0
diff --git a/mips/rtl/mips/mathu.inc b/mips/rtl/mips/mathu.inc
index 9f3ffff15a..8b3063dfa6 100644
--- a/mips/rtl/mips/mathu.inc
+++ b/mips/rtl/mips/mathu.inc
@@ -13,8 +13,29 @@
**********************************************************************}
{ exported by the system unit }
-//!!!function get_fsr : dword;external name 'FPC_GETFSR';
-//!!!procedure set_fsr(fsr : dword);external name 'FPC_SETFSR';
+function get_fsr : dword;external name 'FPC_GETFSR';
+procedure set_fsr(fsr : dword);external name 'FPC_SETFSR';
+
+const
+ { FPU enable exception bits for FCSR register }
+ fpu_enable_inexact = $80;
+ fpu_enable_underflow = $100;
+ fpu_enable_overflow = $200;
+ fpu_enable_div_zero = $400;
+ fpu_enable_invalid = $800;
+ fpu_enable_mask = $F80;
+ default_fpu_enable = fpu_enable_div_zero or fpu_enable_invalid;
+
+ fpu_flags_mask = $7C;
+ fpu_cause_mask = $3F000;
+
+ { FPU rounding mask and values }
+ fpu_rounding_mask = $3;
+ fpu_rounding_nearest = 0;
+ fpu_rounding_towards_zero = 1;
+ fpu_rounding_plus_inf = 2;
+ fpu_rounding_minus_inf = 3;
+
function FPUExceptionMaskToSoftFloatMask(const Mask: TFPUExceptionMask): byte;
begin
@@ -35,22 +56,37 @@ end;
function GetRoundMode: TFPURoundingMode;
begin
-//!!! result:=TFPURoundingMode(get_fsr shr 30);
+ result:=TFPURoundingMode(get_fsr and 3);
end;
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
+ var
+ fpu_round : longint;
begin
+
case (RoundMode) of
rmNearest :
- softfloat_rounding_mode := float_round_nearest_even;
+ begin
+ softfloat_rounding_mode := float_round_nearest_even;
+ fpu_round:=fpu_rounding_nearest;
+ end;
rmTruncate :
- softfloat_rounding_mode := float_round_to_zero;
- rmUp :
- softfloat_rounding_mode := float_round_up;
- rmDown :
- softfloat_rounding_mode := float_round_down;
- end;
-//!!! set_fsr((get_fsr and $3fffffff) or (dword(RoundMode) shl 30));
+ begin
+ softfloat_rounding_mode := float_round_to_zero;
+ fpu_round:=fpu_rounding_towards_zero;
+ end;
+ rmUp :
+ begin
+ softfloat_rounding_mode := float_round_up;
+ fpu_round:=fpu_rounding_plus_inf;
+ end;
+ rmDown :
+ begin
+ softfloat_rounding_mode := float_round_down;
+ fpu_round:=fpu_rounding_minus_inf;
+ end;
+ end;
+ set_fsr((get_fsr and not fpu_rounding_mask) or fpu_round);
//!!! result:=TFPURoundingMode(get_fsr shr 30);
end;
@@ -71,26 +107,26 @@ function GetExceptionMask: TFPUExceptionMask;
var
fsr : dword;
begin
-//!!! fsr:=get_fsr;
+ fsr:=get_fsr;
result:=[];
- { invalid operation: bit 27 }
- if (fsr and (1 shl 27))=0 then
+ { invalid operation }
+ if (fsr and fpu_enable_invalid)=0 then
include(result,exInvalidOp);
- { zero divide: bit 24 }
- if (fsr and (1 shl 24))=0 then
- include(result,exInvalidOp);
+ { zero divide }
+ if (fsr and fpu_enable_div_zero)=0 then
+ include(result,exZeroDivide);
- { overflow: bit 26 }
- if (fsr and (1 shl 26))=0 then
- include(result,exInvalidOp);
+ { overflow }
+ if (fsr and fpu_enable_overflow)=0 then
+ include(result,exOverflow);
- { underflow: bit 25 }
- if (fsr and (1 shl 25))=0 then
+ { underflow: }
+ if (fsr and fpu_enable_underflow)=0 then
include(result,exUnderflow);
- { Precision (inexact result): bit 23 }
- if (fsr and (1 shl 23))=0 then
+ { Precision (inexact result) }
+ if (fsr and fpu_enable_inexact)=0 then
include(result,exPrecision);
end;
@@ -100,40 +136,43 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
var
fsr : dword;
begin
-//!!! fsr:=get_fsr;
+ fsr:=get_fsr;
- { invalid operation: bit 27 }
+ { invalid operation }
if (exInvalidOp in mask) then
- fsr:=fsr and not(1 shl 27)
+ fsr:=fsr and not(fpu_enable_invalid)
else
- fsr:=fsr or (1 shl 27);
+ fsr:=fsr or (fpu_enable_invalid);
- { zero divide: bit 24 }
+ { zero divide }
if (exZeroDivide in mask) then
- fsr:=fsr and not(1 shl 24)
+ fsr:=fsr and not(fpu_enable_div_zero)
else
- fsr:=fsr or (1 shl 24);
+ fsr:=fsr or (fpu_enable_div_zero);
- { overflow: bit 26 }
+ { overflow }
if (exOverflow in mask) then
- fsr:=fsr and not(1 shl 26)
+ fsr:=fsr and not(fpu_enable_overflow)
else
- fsr:=fsr or (1 shl 26);
+ fsr:=fsr or (fpu_enable_overflow);
- { underflow: bit 25 }
+ { underflow }
if (exUnderflow in mask) then
- fsr:=fsr and not(1 shl 25)
+ fsr:=fsr and not(fpu_enable_underflow)
else
- fsr:=fsr or (1 shl 25);
+ fsr:=fsr or (fpu_enable_underflow);
- { Precision (inexact result): bit 23 }
+ { Precision (inexact result) }
if (exPrecision in mask) then
- fsr:=fsr and not(1 shl 23)
+ fsr:=fsr and not(fpu_enable_inexact)
else
- fsr:=fsr or (1 shl 23);
+ fsr:=fsr or (fpu_enable_inexact);
+
+ { Reset flags and cause }
+ fsr := fsr and not (fpu_flags_mask or fpu_cause_mask);
{ update control register contents }
-//!!! set_fsr(fsr);
+ set_fsr(fsr);
softfloat_exception_mask:=FPUExceptionMaskToSoftFloatMask(mask);
end;
@@ -141,6 +180,6 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
procedure ClearExceptions(RaisePending: Boolean =true);
begin
-//!!! set_fsr(get_fsr and $fffffc1f);
+ set_fsr(get_fsr and not (fpu_flags_mask or fpu_cause_mask));
end;
diff --git a/mips/rtl/mips/mips.inc b/mips/rtl/mips/mips.inc
index 22c0ba4dc6..f0d839c164 100644
--- a/mips/rtl/mips/mips.inc
+++ b/mips/rtl/mips/mips.inc
@@ -37,6 +37,26 @@ function get_got_z : pointer;assembler;nostackframe;[public, alias: 'FPC_GETGOT_
move $2,$28
end;
+const
+ { FPU enable exception bits for FCSR register }
+ fpu_enable_inexact = $80;
+ fpu_enable_underflow = $100;
+ fpu_enable_overflow = $200;
+ fpu_enable_div_zero = $400;
+ fpu_enable_invalid = $800;
+ fpu_enable_mask = $F80;
+ default_fpu_enable = fpu_enable_div_zero or fpu_enable_invalid;
+
+ fpu_flags_mask = $7C;
+ fpu_cause_mask = $3F000;
+
+ { FPU rounding mask and values }
+ fpu_rounding_mask = $3;
+ fpu_rounding_nearest = 0;
+ fpu_rounding_towards_zero = 1;
+ fpu_rounding_plus_inf = 2;
+ fpu_rounding_minus_inf = 3;
+
procedure fpc_cpuinit;
var
@@ -45,11 +65,17 @@ var
{ don't let libraries influence the FPU cw set by the host program }
if not IsLibrary then
begin
- { enable div by 0 and invalid operation fpu exceptions }
+ tmp32 := get_fsr();
+ { enable div by 0 and invalid operation fpu exceptions,
+ disable the other exceptions }
+ tmp32 := (tmp32 and not fpu_enable_mask) or default_fpu_enable;
+ { Reset flags and cause }
+ tmp32 := tmp32 and not (fpu_flags_mask or fpu_cause_mask);
+
{ round towards nearest; ieee compliant arithmetics }
+ tmp32 := (tmp32 and not fpu_rounding_mask) or fpu_rounding_nearest;
- tmp32 := get_fsr();
- set_fsr(tmp32 and $fffffffc);
+ set_fsr(tmp32);
end;
end;
@@ -70,25 +96,105 @@ function get_frame:pointer;assembler;nostackframe;
Further, we need to know the pc
}
// lw $2,0($sp)
- lui $2,0
+ move $2,$30
end;
-{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
- asm
- // lw $2,4($4) // #movl 4(%eax),%eax
- lui $2,0
+{ Try to find previous $fp,$ra register pair
+ reset both to nil if failure }
+{$define FPC_SYSTEM_HAS_GET_CALLER_STACKINFO}
+procedure get_caller_stackinfo(var framebp,addr : pointer);
+const
+ instr_size = 4;
+ MAX_INSTRUCTIONS = 64000;
+type
+ instr_p = pdword;
+ reg_p = ppointer;
+var
+ instr,stackpos : dword;
+ i,LocalSize : longint;
+ ra_offset, s8_offset : longint;
+ current_ra : pointer;
+begin
+ { Here we need to use GDB approach,
+ starting at addr
+ go back to lower $ra values until we find a
+ position with ADDIU $sp,$sp,-LocalSize
+ }
+ if addr=nil then
+ begin
+ framebp:=nil;
+ exit;
+ end;
+ Try
+ current_ra:=addr;
+ ra_offset:=-1;
+ s8_offset:=-1;
+ i:=0;
+ LocalSize:=0;
+ repeat
+ inc(i);
+ dec(current_ra,4);
+ instr:=instr_p(current_ra)^;
+ if (instr shr 16 = $27bd) then
+ begin
+ { we found the instruction,
+ local size is the lo part }
+ LocalSize:=smallint(instr and $ffff);
+ break;
+ end;
+ until i> MAX_INSTRUCTIONS;
+ if LocalSize <> 0 then
+ begin
+ repeat
+ inc(current_ra,4);
+ instr:=instr_p(current_ra)^;
+ if (instr shr 16 = $afbf) then
+ ra_offset:=smallint(instr and $ffff)
+ else if (instr shr 16 = $afbe) then
+ s8_offset:=smallint(instr and $ffff);
+ until (current_ra >= addr)
+ or ((ra_offset<>-1) and (s8_offset<>-1));
+ if ra_offset<>-1 then
+ begin
+ stackpos:=dword(framebp+LocalSize+ra_offset);
+ addr:=reg_p(stackpos)^;
+ end
+ else
+ addr:=nil;
+ if s8_offset<>-1 then
+ begin
+ stackpos:=dword(framebp+LocalSize+s8_offset);
+ framebp:=reg_p(stackpos)^;
+ end
+ else
+ framebp:=nil;
+ end;
+ Except
+ framebp:=nil;
+ addr:=nil;
end;
+end;
+{$define FPC_SYSTEM_HAS_GET_PC_ADDR}
+function get_pc_addr : pointer;assembler;nostackframe;
+asm
+ move $2,$31
+end;
-{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
- asm
- // lw $2,0($4) // #movl (%eax),%eax
- lui $2,0
- end;
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
+begin
+ get_caller_stackinfo(framebp,addr);
+ get_caller_addr:=addr;
+end;
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
+begin
+ get_caller_stackinfo(framebp,addr);
+ get_caller_frame:=framebp;
+end;
{$define FPC_SYSTEM_HAS_SPTR}
function Sptr:Pointer;assembler;nostackframe;
diff --git a/mips/rtl/objpas/fgl.pp b/mips/rtl/objpas/fgl.pp
index 1418c1cbb7..0b6670334f 100644
--- a/mips/rtl/objpas/fgl.pp
+++ b/mips/rtl/objpas/fgl.pp
@@ -1164,7 +1164,7 @@ end;
function TFPSMap.BinaryCompareData(Data1, Data2: Pointer): Integer;
begin
- Result := CompareByte(Data1^, Data1^, FDataSize);
+ Result := CompareByte(Data1^, Data2^, FDataSize);
end;
procedure TFPSMap.SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
diff --git a/mips/rtl/objpas/strutils.pp b/mips/rtl/objpas/strutils.pp
index 8290314cb6..aef57f043e 100644
--- a/mips/rtl/objpas/strutils.pp
+++ b/mips/rtl/objpas/strutils.pp
@@ -97,6 +97,13 @@ Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
function StringsReplace(const S: string; OldPattern, NewPattern: array of string; Flags: TReplaceFlags): string;
{ ---------------------------------------------------------------------
+ Delphi compat
+ ---------------------------------------------------------------------}
+
+Function ReplaceStr(const AText, AFromText, AToText: string): string;inline;
+Function ReplaceText(const AText, AFromText, AToText: string): string;inline;
+
+{ ---------------------------------------------------------------------
Soundex Functions.
---------------------------------------------------------------------}
@@ -745,6 +752,20 @@ begin
end;
{ ---------------------------------------------------------------------
+ Delphi compat
+ ---------------------------------------------------------------------}
+
+Function ReplaceStr(const AText, AFromText, AToText: string): string;inline;
+begin
+ AnsiReplaceStr(AText, AFromText, AToText);
+end;
+
+Function ReplaceText(const AText, AFromText, AToText: string): string;inline;
+begin
+ AnsiReplaceText(AText, AFromText, AToText);
+end;
+
+{ ---------------------------------------------------------------------
Soundex Functions.
---------------------------------------------------------------------}
Const
diff --git a/mips/rtl/openbsd/errno.inc b/mips/rtl/openbsd/errno.inc
index b5013276da..2f41d87ce2 100644
--- a/mips/rtl/openbsd/errno.inc
+++ b/mips/rtl/openbsd/errno.inc
@@ -78,7 +78,6 @@ Const
ESysEPROTONOSUPPORT = 43; { Protocol not supported }
ESysESOCKTNOSUPPORT = 44; { Socket type not supported }
ESysEOPNOTSUPP = 45; { Operation not supported }
- ESysENOTSUP = ESysEOPNOTSUPP; { Operation not supported }
ESysEPFNOSUPPORT = 46; { Protocol family not supported }
ESysEAFNOSUPPORT = 47; { Address family not supported by protocol family }
ESysEADDRINUSE = 48; { Address already in use }
@@ -126,12 +125,15 @@ Const
ESysEFTYPE = 79; { Inappropriate file type or format }
ESysEAUTH = 80; { Authentication error }
ESysENEEDAUTH = 81; { Need authenticator }
- ESysEIDRM = 82; { Identifier removed }
- ESysENOMSG = 83; { No message of desired type }
- ESysEOVERFLOW = 84; { Value too large to be stored in data type }
- ESysECANCELED = 85; { Operation canceled }
- ESysEILSEQ = 86; { Illegal byte sequence }
- ESysELAST = 86; { Must be equal largest errno }
-
-
+ ESysEIPSEC = 82; { IPsec processing failure }
+ ESysENOATTR = 83; { Attribute not found }
+ ESysEILSEQ = 84; { Illegal byte sequence }
+ ESysENOMEDIUM = 85; { No medium found }
+ ESysEMEDIUMTYPE = 86; { Wrong Medium Type }
+ ESysEOVERFLOW = 87; { Value too large to be stored in data type }
+ ESysECANCELED = 88; { Operation canceled }
+ ESysEIDRM = 89; { Identifier removed }
+ ESysENOMSG = 90; { No message of desired type }
+ ESysENOTSUP = 91; { Not supported }
+ ESysELAST = ESysENOTSUP; { Must be equal largest errno }
diff --git a/mips/rtl/powerpc/powerpc.inc b/mips/rtl/powerpc/powerpc.inc
index 7a8645e007..278d53df68 100644
--- a/mips/rtl/powerpc/powerpc.inc
+++ b/mips/rtl/powerpc/powerpc.inc
@@ -1024,7 +1024,7 @@ indicated by the first bit set to 1. This is checked below.}
{Both routines below assumes that framebp is a valid framepointer or nil.}
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
asm
cmplwi r3,0
beq .Lcaller_addr_invalid
@@ -1048,7 +1048,7 @@ end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
asm
cmplwi r3,0
beq .Lcaller_frame_invalid
diff --git a/mips/rtl/powerpc64/powerpc64.inc b/mips/rtl/powerpc64/powerpc64.inc
index f613bb7ddb..53dc54f7b1 100644
--- a/mips/rtl/powerpc64/powerpc64.inc
+++ b/mips/rtl/powerpc64/powerpc64.inc
@@ -520,7 +520,7 @@ asm
end;
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
asm
cmpldi r3,0
beq .Lcaller_addr_frame_null
@@ -534,7 +534,7 @@ end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
asm
cmpldi r3,0
beq .Lcaller_frame_null
diff --git a/mips/rtl/sparc/sparc.inc b/mips/rtl/sparc/sparc.inc
index a4b30eb84d..d773161802 100644
--- a/mips/rtl/sparc/sparc.inc
+++ b/mips/rtl/sparc/sparc.inc
@@ -53,7 +53,7 @@ Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
round towards zero; ieee compliant arithmetics }
set_fsr((get_fsr and $3fbfffff) or $09000000);
end;
-
+
{$define FPC_SYSTEM_HAS_SYSRESETFPU}
Procedure SysResetFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
begin
@@ -77,7 +77,7 @@ function get_frame:pointer;assembler;nostackframe;
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
asm
{ framebp = %o0 }
subcc %o0,0,%o0
@@ -93,7 +93,7 @@ function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
asm
{ framebp = %o0 }
subcc %o0,0,%o0
diff --git a/mips/rtl/unix/ipc.pp b/mips/rtl/unix/ipc.pp
index b506ea9012..66e9e3c13e 100644
--- a/mips/rtl/unix/ipc.pp
+++ b/mips/rtl/unix/ipc.pp
@@ -548,12 +548,12 @@ const
MAX_SOPS = 5;
{$if not defined(aix) and not defined(darwin)}
- SEM_GETNCNT = 3; { Return the value of sempid {READ} }
- SEM_GETPID = 4; { Return the value of semval {READ} }
- SEM_GETVAL = 5; { Return semvals into arg.array {READ} }
- SEM_GETALL = 6; { Return the value of semzcnt {READ} }
- SEM_GETZCNT = 7; { Set the value of semval to arg.val {ALTER} }
- SEM_SETVAL = 8; { Set semvals from arg.array {ALTER} }
+ SEM_GETNCNT = 3; { Return the value of sempid (READ) }
+ SEM_GETPID = 4; { Return the value of semval (READ) }
+ SEM_GETVAL = 5; { Return semvals into arg.array (READ) }
+ SEM_GETALL = 6; { Return the value of semzcnt (READ) }
+ SEM_GETZCNT = 7; { Set the value of semval to arg.val (ALTER) }
+ SEM_SETVAL = 8; { Set semvals from arg.array (ALTER) }
SEM_SETALL = 9;
{$endif}
diff --git a/mips/rtl/unix/scripts/check_consts.sh b/mips/rtl/unix/scripts/check_consts.sh
index 8f6655bdc9..a7e08b1556 100755
--- a/mips/rtl/unix/scripts/check_consts.sh
+++ b/mips/rtl/unix/scripts/check_consts.sh
@@ -20,6 +20,8 @@ os=`uname -s`
if [ "$os" == "NetBSD" ] ; then
needgsed=1
+else
+ needgsed=0
fi
SED=sed
@@ -37,7 +39,7 @@ fi
for file in $@ ; do
echo "Looking for constants in \"$file\""
-$SED -n "s:.*[[:space:]]\([a-zA-Z_][a-zA-Z_0-9]*\)[[:space:]]*=[[:space:]]*\([-+]*[0-9][xX]*[0-9+-\*/]*\)[[:space:]]*;.*:test_const \1 \2:p" $file > check_const_list.sh
+$SED -n -e "s:.*[[:space:]]\([a-zA-Z_][a-zA-Z_0-9]*\)[[:space:]]*=[[:space:]]*\([-+]*[0-9][xX]*[-0-9+[:space:]]*\)[[:space:]]*;.*:test_const \1 \2:p" $file > check_const_list.sh
test_const ()
{
diff --git a/mips/rtl/unix/scripts/check_errno.sh b/mips/rtl/unix/scripts/check_errno.sh
index 22f10d4d6a..c07e28a0f2 100755
--- a/mips/rtl/unix/scripts/check_errno.sh
+++ b/mips/rtl/unix/scripts/check_errno.sh
@@ -21,10 +21,24 @@ else
verbose=0
fi
+if [ "$1" == "addall" ] ; then
+ addall=1
+ echo "Adding all entries to errno-new.inc"
+ shift
+else
+ addall=0
+fi
+
# Location of error number in system header
-errno_header="/usr/include/asm-generic/errno-base.h /usr/include/asm-generic/errno.h"
-errno_include=./errno.inc
+errno_headers="/usr/include/asm-generic/errno-base.h /usr/include/asm-generic/errno.h"
+
+if [ "$1" != "" ] ; then
+ errno_include=$1
+ echo "Using $errno_include file"
+else
+ errno_include=./errno.inc
+fi
# Sustitution made to pass from fpc syscall number
# to system define
@@ -53,18 +67,53 @@ fi
# Use gcc with --save-temps option to create .i file
$CC --save-temps -c ./test-errno.c
# list of errno.h headers listed
-errno_headers=` sed -n "s:.*\"\(.*\.h\)\".*:\1:p" test-errno.i |sort | uniq`
-echo "Headers found are \"$errno_headers\""
+errno_headers_CC=` sed -n "s:.*\"\(.*\.h\)\".*:\1:p" test-errno.i |sort | uniq`
+echo "Headers found are \"$errno_headers_CC\""
-if [ "$errno_headers" != "" ] ; then
- errno_header="$errno_headers"
+if [ "$errno_headers_CC" != "" ] ; then
+ errno_headers="$errno_headers_CC"
fi
# You should only need to change the variables above
sed -n "s:^[[:space:]]*${fpc_errno_prefix}\\([_a-zA-Z0-9]*\\)[[:space:]]*=[[:space:]]*\\([0-9][0-9]*\\).*:check_errno_number ${errno_prefix}\1 \2:p" ${errno_include} > check_errno_list.sh
-sed -n "s:#define[[:space:]]*${errno_prefix}\\([_a-zA-Z0-9]*\\)[[:space:]][[:space:]]*\\(-*[0-9A-Za-z_]*\\).*:check_reverse_errno_number ${fpc_errno_prefix}\1 \2:p" ${errno_header} > check_reverse_errno_list.sh
+sed -n "s:#define[[:space:]]*${errno_prefix}\\([_a-zA-Z0-9]*\\)[[:space:]][[:space:]]*\\(-*[0-9A-Za-z_]*\\)[[:space:]]*\(.*\):check_reverse_errno_number ${fpc_errno_prefix}\1 \2 \"\3\":p" ${errno_headers} > check_reverse_errno_list.sh
+
+function rpad {
+ word="$1"
+ while [ ${#word} -lt $2 ]; do
+ word="$word$3";
+ done;
+ echo "$word";
+}
+
+function compile_errno ()
+{
+ errname=$1
+ errvalue=$2
+# Test C file to grab all loaded headers
+cat > test-errno.c <<EOF
+#include <errno.h>
+#include <stdio.h>
+
+int
+main ()
+{
+ printf ("$errname=%d\n",$errname);
+ return 0;
+}
+EOF
+$CC -o ./test-errno ./test-errno.c
+compiledvalue=`./test-errno`
+if [ "$compiledvalue" == "$errname=$errvalue" ] ; then
+ if [ $verbose -ne 0 ]; then
+ echo "GCC reports $compiledvalue OK"
+ fi
+else
+ echo "GCC reports $compiledvalue, but $errvalue is expected"
+fi
+}
function check_errno_number ()
{
@@ -75,10 +124,11 @@ function check_errno_number ()
fi
# Remember value of this constant
eval ${sys}=${value}
+ compile_errno $sys $value
- found=`sed -n "/#define[[:space:]][[:space:]]*${sys}[^A-Za-z0-9_]/p" ${errno_header}`
- val=`sed -n "s:#define[[:space:]][[:space:]]*${sys}[^A-Za-z0-9_][^A-Za-z0-9_]*\([0-9]*\).*:\1:p" ${errno_header}`
- extval=`sed -n "s:#define[[:space:]][[:space:]]*${sys}[^A-Za-z0-9_][^A-Za-z0-9_]*\([0-9A-Za-z_]*\).*:\1:p" ${errno_header}`
+ found=`sed -n "/#define[[:space:]][[:space:]]*${sys}[^A-Za-z0-9_]/p" ${errno_headers}`
+ val=`sed -n "s:#define[[:space:]][[:space:]]*${sys}[^A-Za-z0-9_][^A-Za-z0-9_]*\([0-9]*\).*:\1:p" ${errno_headers}`
+ extval=`sed -n "s:#define[[:space:]][[:space:]]*${sys}[^A-Za-z0-9_][^A-Za-z0-9_]*\([0-9A-Za-z_]*\).*:\1:p" ${errno_headers}`
if [ $verbose -ne 0 ] ; then
echo Test for $sys found \"${found}\" \"${value}\" \"${val}\"
fi
@@ -87,13 +137,16 @@ function check_errno_number ()
echo ${sys} value ${val} is correct
fi
else
+ if [ $verbose -ne 0 ] ; then
+ echo "${sys} val=\"$val\", extval=\"$extval\""
+ fi
if [ "${val}" == "" ] ; then
- foundvalue=`sed -n "/#define.*[^A-Za-z0-9_]${value}$/p" ${errno_header}`
+ foundvalue=`sed -n "/#define.*[^A-Za-z0-9_]${value}$/p" ${errno_headers}`
if [ "${foundvalue}" == "" ] ; then
- foundvalue=`sed -n "s:\/\* ${value} is compa: ${value} is compa:p" ${errno_header}`
+ foundvalue=`sed -n "s:\/\* ${value} is compa: ${value} is compa:p" ${errno_headers}`
fi
fi
- if [ "$extval" != "" ] ; then
+ if [ "$extval" != "$val" ] ; then
eval indirectval=\$$extval
echo "indirectval =\"$indirectval\" for \"$extval\""
if [ "$indirectval" != "$value" ] ; then
@@ -107,19 +160,46 @@ function check_errno_number ()
fi
}
+function write_errno_new_head ()
+{
+ echo "{ File generated by $0" > $errnonew
+ uname_info=`uname -s -r -m`
+ echo " generated on \"$uname_info\" machine" >> $errnonew
+ echo "List of missing system error number found in" >> $errnonew
+ echo "$errno_headers" >> $errnonew
+ echo "}" >> $errnonew
+}
function check_reverse_errno_number ()
{
errname=$1
errvalue=$2
+ rpaderrname=$(rpad $errname 20 " ")
+ if ! [[ "$errvalue" =~ ^[0-9]+$ ]] ; then
+ eval errvalue=\$$errvalue
+ fi
+
+ printf -v padd "%s = %4d" "$rpaderrname" $errvalue
+
found=`grep -i -w $1 ${errno_include}`
+ comment="$3"
+ comment=${comment##\/\*}
+ comment=${comment%%\*\/}
if [ "${found}" == "" ] ; then
echo "Error ${errname}, value ${errvalue}, not in ${errno_include} file"
if [ $addtoerrno -eq 0 ] ; then
addtoerrno=1
- echo "{ List of missing system error number found in $errno_header }" > $errnonew
+ write_errno_new_head
+ fi
+ echo " $padd; { $comment }" >> $errnonew
+ else
+ if [ $addall -eq 1 ] ; then
+ if [ $addtoerrno -eq 0 ] ; then
+ addtoerrno=1
+ write_errno_new_head
+ fi
+ echo " $padd; { $comment }" >> $errnonew
fi
- echo " $errname = $errvalue;" >> $errnonew
fi
}
diff --git a/mips/rtl/win/crt.pp b/mips/rtl/win/crt.pp
index 6369f4c247..824b31e44f 100644
--- a/mips/rtl/win/crt.pp
+++ b/mips/rtl/win/crt.pp
@@ -711,7 +711,14 @@ begin
WriteChar(f.buffer[i]);
end
else
- s:=s+f.buffer[i];
+ begin
+ if length(s)=255 then
+ begin
+ WriteStr(s);
+ s:='';
+ end;
+ s:=s+f.buffer[i];
+ end;
if s<>'' then
WriteStr(s);
SetScreenCursor(CurrX, CurrY);
diff --git a/mips/rtl/x86_64/x86_64.inc b/mips/rtl/x86_64/x86_64.inc
index 6a5947ef07..70e11076e4 100644
--- a/mips/rtl/x86_64/x86_64.inc
+++ b/mips/rtl/x86_64/x86_64.inc
@@ -35,9 +35,14 @@ asm
end;
{$ENDIF not INTERNAL_BACKTRACE}
+{$define FPC_SYSTEM_HAS_GET_PC_ADDR}
+function get_pc_addr:pointer;assembler;nostackframe;
+asm
+ movq (%rsp),%rax
+end;
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
-function get_caller_addr(framebp:pointer):pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
begin
get_caller_addr:=framebp;
if assigned(framebp) then
@@ -46,7 +51,7 @@ end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
-function get_caller_frame(framebp:pointer):pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
begin
get_caller_frame:=framebp;
if assigned(framebp) then
@@ -942,7 +947,7 @@ Procedure SysInitFPU;
{ these locals are so we don't have to hack pic code in the assembler }
localmxcsr: dword;
localfpucw: word;
-
+
begin
localmxcsr:=mxcsr;
localfpucw:=fpucw;
diff --git a/mips/tests/Makefile b/mips/tests/Makefile
index cfc720c897..46bc840699 100644
--- a/mips/tests/Makefile
+++ b/mips/tests/Makefile
@@ -1898,6 +1898,7 @@ endif
ifndef TEST_OPT
TEST_OPT=
endif
+override TEST_OPT+=-Fd
ifndef TEST_FPC_VERSION
TEST_FPC_COMPILERINFO:=$(shell $(TEST_FPC) -iVSPTPSOTODW)
TEST_FPC_VERSION:=$(word 1,$(TEST_FPC_COMPILERINFO))
diff --git a/mips/tests/Makefile.fpc b/mips/tests/Makefile.fpc
index da9bd9ea6d..b3c4052845 100644
--- a/mips/tests/Makefile.fpc
+++ b/mips/tests/Makefile.fpc
@@ -36,6 +36,11 @@ ifndef TEST_OPT
TEST_OPT=
endif
+# disable directory cache; completely loading all directories significantly
+# slows down running the testsuite because the programs use very few units
+# and most testsuite directories contain thousands of files
+override TEST_OPT+=-Fd
+
# Retrieve Test compiler info
ifndef TEST_FPC_VERSION
TEST_FPC_COMPILERINFO:=$(shell $(TEST_FPC) -iVSPTPSOTODW)
diff --git a/mips/tests/tbs/tb0193.pp b/mips/tests/tbs/tb0193.pp
index d2b2376b8b..6097cef5b7 100644
--- a/mips/tests/tbs/tb0193.pp
+++ b/mips/tests/tbs/tb0193.pp
@@ -11,15 +11,18 @@ asm
{$ifdef CPUI386}
movl stacksize,%eax
end ['EAX'];
+{$define implemented}
{$endif CPUI386}
{$ifdef CPUX86_64}
movq stacksize@GOTPCREL(%rip),%rax
movq (%rax),%rax
end ['EAX'];
+{$define implemented}
{$endif CPUX86_64}
{$ifdef CPU68K}
move.l stacksize,d0
end ['D0'];
+{$define implemented}
{$endif CPU68K}
{$ifdef cpupowerpc}
{$if not defined(macos) and not defined(aix)}
@@ -30,11 +33,13 @@ end ['D0'];
lwz r3, 0(r3)
{$endif macos}
end;
+{$define implemented}
{$endif cpupowerpc}
{$ifdef cpusparc}
sethi %hi(stacksize),%i0
or %i0,%lo(stacksize),%i0
end;
+{$define implemented}
{$endif cpusparc}
{$ifdef cpuarm}
ldr r0,.Lpstacksize
@@ -44,7 +49,18 @@ end;
.long stacksize
.Lend:
end;
+{$define implemented}
{$endif cpuarm}
+{$ifdef cpumips}
+ la $v0,stacksize
+ lw $v0,($v0)
+ end;
+{$define implemented}
+{$endif cpumips}
+{$ifndef implemented}
+ {$error This test does not supported this CPU}
+end;
+{$endif}
begin
writeln(getstacksize);
diff --git a/mips/tests/tbs/tb0524.pp b/mips/tests/tbs/tb0524.pp
index a7be19e064..ba10a014b0 100644
--- a/mips/tests/tbs/tb0524.pp
+++ b/mips/tests/tbs/tb0524.pp
@@ -1,9 +1,46 @@
-{%TARGET=linux,freebsd,darwin,aix}
+{%TARGET=linux,freebsd,darwin,aix,openbsd,netbsd}
program tb0524;
uses sockets,baseunix,sysutils;
+
const port=6667;
+ textfile = 'tb0524.txt';
+
+procedure reset_textfile;
+var
+ f : text;
+begin
+ assign(f,textfile);
+ rewrite(f);
+ writeln(f,'Normal server start');
+ close(f);
+end;
+
+procedure stop(error : longint);
+var
+ f : text;
+begin
+ assign(f,textfile);
+ rewrite(f);
+ writeln(f,'Server startup failed');
+ close(f);
+ halt(error);
+end;
+
+function server_failed : boolean;
+var
+ f : text;
+ st : string;
+begin
+ server_failed:=false;
+ assign(f,textfile);
+ reset(f);
+ readln(f,st);
+ if pos('Server startup failed',st)=1 then
+ server_failed:=true;
+ close(f);
+end;
procedure do_server;
@@ -15,11 +52,12 @@ var s,t:string;
i:byte;
begin
+ reset_textfile;
lsock:=fpsocket(af_inet,sock_stream,0);
if lsock=-1 then
begin
- writeln('socket:',socketerror);
- halt(1);
+ writeln('socket call error:',socketerror);
+ stop(1);
end;
with saddr do
@@ -31,22 +69,22 @@ begin
if fpbind(lsock,@saddr,sizeof(saddr))<>0 then
begin
- writeln('bind:',socketerror);
- halt(1);
+ writeln('bind call error:',socketerror);
+ stop(1);
end;
if fplisten(lsock,1)<>0 then
begin
- writeln('listen:',socketerror);
- halt(1);
+ writeln('listen call error:',socketerror);
+ stop(1);
end;
len:=sizeof(saddr);
usock:=fpaccept(lsock,@saddr,@len);
if usock=-1 then
begin
- writeln('accept:',SocketError);
- halt(1);
+ writeln('accept call error:',SocketError);
+ stop(1);
end;
sock2text(usock,sin,sout);
@@ -101,6 +139,12 @@ begin
begin
{Give server some time to start.}
sleep(2000);
- do_client;
+ if server_failed then
+ begin
+ writeln('Server startup failed, test can not be completed');
+ halt(2);
+ end
+ else
+ do_client;
end;
end.
diff --git a/mips/tests/tbs/tb0528.pp b/mips/tests/tbs/tb0528.pp
index 8a6899c5a0..d362385828 100644
--- a/mips/tests/tbs/tb0528.pp
+++ b/mips/tests/tbs/tb0528.pp
@@ -2,7 +2,7 @@
{%skiptarget=darwin,aix}
{ darwin limits statically declared data structures to 32 bit for efficiency reasons }
-{ the aix assembler cannot deal with the way we declare these arrays in assembler code )
+{ the aix assembler cannot deal with the way we declare these arrays in assembler code }
program tb0528;
diff --git a/mips/tests/test/jvm/tenum2.pp b/mips/tests/test/jvm/tenum2.pp
new file mode 100644
index 0000000000..a485691298
--- /dev/null
+++ b/mips/tests/test/jvm/tenum2.pp
@@ -0,0 +1,34 @@
+program tenum2;
+
+{$mode delphi}
+
+type
+ tenum2enum = (e_zero, e_one, e_two);
+
+ tenum2base = class abstract
+ constructor create;
+ procedure init; virtual; abstract;
+ end;
+
+ tenum2child = class(tenum2base)
+ fenum: tenum2enum;
+ procedure init; override;
+ end;
+
+constructor tenum2base.create;
+ begin
+ init;
+ end;
+
+procedure tenum2child.init;
+ begin
+ fenum:=e_one;
+ end;
+
+var
+ c: tenum2child;
+begin
+ c:=tenum2child.create;
+ if c.fenum<>e_one then
+ halt(1);
+end.
diff --git a/mips/tests/test/jvm/testall.bat b/mips/tests/test/jvm/testall.bat
index 2435e66f15..594e8b76f6 100644
--- a/mips/tests/test/jvm/testall.bat
+++ b/mips/tests/test/jvm/testall.bat
@@ -64,10 +64,14 @@ if %errorlevel% neq 0 exit /b %errorlevel%
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tbyte
if %errorlevel% neq 0 exit /b %errorlevel%
del uenum.ppu
-ppcjvm -O2 -g tenum
+ppcjvm -O2 -g -CTenumfieldinit tenum
if %errorlevel% neq 0 exit /b %errorlevel%
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tenum
if %errorlevel% neq 0 exit /b %errorlevel%
+ppcjvm -O2 -g tenum2
+if %errorlevel% neq 0 exit /b %errorlevel%
+java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tenum2
+if %errorlevel% neq 0 exit /b %errorlevel%
ppcjvm -O2 -g tprop
if %errorlevel% neq 0 exit /b %errorlevel%
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop
@@ -236,4 +240,7 @@ ppcjvm -O2 -g -B taddbool
if %errorlevel% neq 0 exit /b %errorlevel%
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. -Sa TAddBool
if %errorlevel% neq 0 exit /b %errorlevel%
-
+ppcjvm -O2 -g -B tsetansistr
+if %errorlevel% neq 0 exit /b %errorlevel%
+java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. -Sa tsetansistr
+if %errorlevel% neq 0 exit /b %errorlevel%
diff --git a/mips/tests/test/jvm/testall.sh b/mips/tests/test/jvm/testall.sh
index c80baf74a9..ddd869b8a7 100755
--- a/mips/tests/test/jvm/testall.sh
+++ b/mips/tests/test/jvm/testall.sh
@@ -47,8 +47,10 @@ $PPC -O2 -g forw
$PPC -O2 -g tbyte
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tbyte
rm -f uenum.ppu
-$PPC -O2 -g tenum
+$PPC -O2 -g -CTenumfieldinit tenum
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tenum
+$PPC -O2 -g tenum2
+java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tenum2
$PPC -O2 -g tprop
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop
$PPC -O2 -g tprop2
@@ -133,3 +135,5 @@ $PPC -O2 -g -B -Sa tassert
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tassert
$PPC -O2 -g -B -Sa taddbool
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. TAddBool
+$PPC -O2 -g -B -Sa tsetansistr
+java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tsetansistr
diff --git a/mips/tests/test/jvm/tsetansistr.pp b/mips/tests/test/jvm/tsetansistr.pp
new file mode 100644
index 0000000000..1dd983dff0
--- /dev/null
+++ b/mips/tests/test/jvm/tsetansistr.pp
@@ -0,0 +1,31 @@
+program tsetansistr;
+
+{$mode delphi}
+{$modeswitch unicodestrings}
+
+type
+ ByteArray = array of byte;
+
+const
+ AnsiStrOffset = 1;
+
+function AnsiStringOfBytes(const Src : ByteArray) : AnsiString;
+var
+ i : integer;
+begin
+ SetLength(Result, Length(Src));
+
+ for i := 0 to Length(Src) - 1 do
+ Result[i + AnsiStrOffset] := Chr(Src[i]);
+end;
+
+var
+ A : ByteArray;
+ B : AnsiString;
+begin
+ DefaultSystemCodePage:=20127; // ASCII
+ SetLength(A, 1); A[0] := $98;
+ B := AnsiStringOfBytes(A);
+ if ord(B[1]) <> $98 then
+ halt(1);
+end.
diff --git a/mips/tests/test/opt/tretopt.pp b/mips/tests/test/opt/tretopt.pp
index b10ac0933d..fa1294bd21 100644
--- a/mips/tests/test/opt/tretopt.pp
+++ b/mips/tests/test/opt/tretopt.pp
@@ -294,7 +294,7 @@ begin
{$ifdef darwin}
movl %eax,p3-.Lpic(%ecx)
{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
+ addl $_GLOBAL_OFFSET_TABLE_+1,%ecx
movl %eax,p3@GOT(%ecx)
{$endif darwin}
{$endif FPC_PIC}
@@ -349,7 +349,7 @@ begin
{$ifdef darwin}
movl %eax,p3-.Lpic(%ecx)
{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
+ addl $_GLOBAL_OFFSET_TABLE_+1,%ecx
movl %eax,p3@GOT(%ecx)
{$endif darwin}
{$endif FPC_PIC}
diff --git a/mips/tests/test/packages/bzip2/tbzip2streamtest.pp b/mips/tests/test/packages/bzip2/tbzip2streamtest.pp
index b82616c5be..dfa10fe6ba 100644
--- a/mips/tests/test/packages/bzip2/tbzip2streamtest.pp
+++ b/mips/tests/test/packages/bzip2/tbzip2streamtest.pp
@@ -70,53 +70,56 @@ begin
UncompressedFile:=SysUtils.GetTempFileName(EmptyStr, 'UNC');
CompressedFile:=SysUtils.GetTempFileName(EmptyStr, 'BZ2');
- // Set up test bz2 file
- // create a resource stream which points to our resource
- ExampleFileResourceStream := TResourceStream.Create(HInstance, 'ALL', 'RT_RCDATA');
try
- ExampleFileStream := TFileStream.Create(CompressedFile, fmCreate);
+ // Set up test bz2 file
+ // create a resource stream which points to our resource
+ ExampleFileResourceStream := TResourceStream.Create(HInstance, 'ALL', 'RT_RCDATA');
try
- ExampleFileStream.CopyFrom(ExampleFileResourceStream, ExampleFileResourceStream.Size);
+ ExampleFileStream := TFileStream.Create(CompressedFile, fmCreate);
+ try
+ ExampleFileStream.CopyFrom(ExampleFileResourceStream, ExampleFileResourceStream.Size);
+ finally
+ ExampleFileStream.Free;
+ end;
finally
- ExampleFileStream.Free;
+ ExampleFileResourceStream.Free;
end;
- finally
- ExampleFileResourceStream.Free;
- end;
- // Actual decompression
- if decompress(CompressedFile, UncompressedFile) then
- begin
- // Now check if contents match.
- UncompressedHash:=MD5Print(MD5File(UncompressedFile, MDDefBufSize));
- if UncompressedHash=ExpectedHash then
- begin
- code:=0; //success
- end
- else
- begin
- writeln('MD5 hash comparison between original file and uncompressed file failed');
- writeln('Got hash:'+UncompressedHash);
- writeln('Expected:'+ExpectedHash);
- code:=2;
- end;
- end
- else
- begin
- writeln('bunzip2 decompression failure');
- code:=1;
- end;
+ // Actual decompression
+ if decompress(CompressedFile, UncompressedFile) then
+ begin
+ // Now check if contents match.
+ UncompressedHash:=MD5Print(MD5File(UncompressedFile, MDDefBufSize));
+ if UncompressedHash=ExpectedHash then
+ begin
+ code:=0; //success
+ end
+ else
+ begin
+ writeln('MD5 hash comparison between original file and uncompressed file failed');
+ writeln('Got hash:'+UncompressedHash);
+ writeln('Expected:'+ExpectedHash);
+ code:=2;
+ end;
+ end
+ else
+ begin
+ writeln('bunzip2 decompression failure');
+ code:=1;
+ end;
- try
- if CompressedFile<>EmptyStr then DeleteFile(CompressedFile);
- if UncompressedFile<>EmptyStr then DeleteFile(UncompressedFile);
- finally
- // Ignore errors; operating system should clean out temp files
- end;
- if code = 0 then
- writeln('Basic bzip2 tests passed')
- else
- writeln('Basic bzip2 test failed: ', code);
+ if code = 0 then
+ writeln('Basic bzip2 tests passed')
+ else
+ writeln('Basic bzip2 test failed: ', code);
+ finally
+ try
+ if CompressedFile<>EmptyStr then DeleteFile(CompressedFile);
+ if UncompressedFile<>EmptyStr then DeleteFile(UncompressedFile);
+ finally
+ // Ignore errors; operating system should clean out temp files
+ end;
+ end;
Halt(code);
end.
diff --git a/mips/tests/test/tasmread.pp b/mips/tests/test/tasmread.pp
index c3ac8fd3a8..b7c0bf7372 100644
--- a/mips/tests/test/tasmread.pp
+++ b/mips/tests/test/tasmread.pp
@@ -20,7 +20,7 @@ begin
{$ifdef darwin}
mov [test.l-@@LPIC+ecx],5
{$else darwin}
- add ecx, _GLOBAL_OFFSET_TABLE_
+ add ecx, _GLOBAL_OFFSET_TABLE_+1
mov [test.l + ecx],5
{$endif darwin}
{$endif FPC_PIC}
diff --git a/mips/tests/test/tcg1.pp b/mips/tests/test/tcg1.pp
index bd8f702c83..59a6818dbc 100644
--- a/mips/tests/test/tcg1.pp
+++ b/mips/tests/test/tcg1.pp
@@ -2,71 +2,32 @@
{$R-}
program test_register_pushing;
-var
- before, after : longint;
- wpush,lpush : longint;
const
haserror : boolean = false;
-
+
+procedure dotest;
+var
+ wpush,lpush: longint;
begin
-{$ifdef CPUI386}
{$asmmode att}
asm
-{$ifndef FPC_PIC}
- movl %esp,before
- pushw %es
- movl %esp,after
- popw %es
-{$else not FPC_PIC}
- call .LPIC
-.LPIC:
- popl %ecx
-{$ifdef darwin}
- movl %esp,before-.LPIC(%ecx)
- pushw %es
- movl %esp,after-.LPIC(%ecx)
- popw %es
-{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
- movl %esp,before@GOT(%ecx)
+ movl %esp,wpush
pushw %es
- movl %esp,after@GOT(%ecx)
+ subl %esp,wpush
popw %es
-{$endif darwin}
-{$endif not FPC_PIC}
end;
- wpush:=before-after;
if wpush<>2 then
begin
Writeln('Compiler does not push "pushw %es" into 2 bytes');
haserror:=true;
end;
+
asm
-{$ifndef FPC_PIC}
- movl %esp,before
+ movl %esp,lpush
pushl %es
- movl %esp,after
+ subl %esp,lpush
popl %es
-{$else not FPC_PIC}
- call .LPIC
-.LPIC:
- popl %ecx
-{$ifdef darwin}
- movl %esp,before-.LPIC(%ecx)
- pushl %es
- movl %esp,after-.LPIC(%ecx)
- popl %es
-{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
- movl %esp,before@GOT(%ecx)
- pushl %es
- movl %esp,after@GOT(%ecx)
- popl %es
-{$endif darwin}
-{$endif not FPC_PIC}
end;
- lpush:=before-after;
-
if lpush<>4 then
begin
Writeln('Compiler does not push "pushl %es" into 4 bytes');
@@ -74,61 +35,22 @@ begin
end;
asm
-{$ifndef FPC_PIC}
- movl %esp,before
- pushw %gs
- movl %esp,after
- popw %gs
-{$else not FPC_PIC}
- call .LPIC
-.LPIC:
- popl %ecx
-{$ifdef darwin}
- movl %esp,before-.LPIC(%ecx)
+ movl %esp,wpush
pushw %gs
- movl %esp,after-.LPIC(%ecx)
+ subl %esp,wpush
popw %gs
-{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
- movl %esp,before@GOT(%ecx)
- pushw %gs
- movl %esp,after@GOT(%ecx)
- popw %gs
-{$endif darwin}
-{$endif not FPC_PIC}
end;
- wpush:=before-after;
if wpush<>2 then
begin
Writeln('Compiler does not push "pushw %gs" into 2 bytes');
haserror:=true;
end;
asm
-{$ifndef FPC_PIC}
- movl %esp,before
- pushl %gs
- movl %esp,after
- popl %gs
-{$else not FPC_PIC}
- call .LPIC
-.LPIC:
- popl %ecx
-{$ifdef darwin}
- movl %esp,before-.LPIC(%ecx)
+ movl %esp,lpush
pushl %gs
- movl %esp,after-.LPIC(%ecx)
+ subl %esp,lpush
popl %gs
-{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
- movl %esp,before@GOT(%ecx)
- pushl %gs
- movl %esp,after@GOT(%ecx)
- popl %gs
-{$endif darwin}
-{$endif not FPC_PIC}
end;
- lpush:=before-after;
-
if lpush<>4 then
begin
Writeln('Compiler does not push "pushl %gs" into 4 bytes');
@@ -136,31 +58,16 @@ begin
end;
{$asmmode intel}
asm
-{$ifndef FPC_PIC}
- mov before,esp
+ mov lpush,esp
push es
- mov after,esp
+ sub lpush,esp
pop es
-{$else not FPC_PIC}
- call @@LPIC
-@@LPIC:
- pop ecx
-{$ifdef darwin}
- mov [before-@@LPIC+ecx],esp
- push es
- mov [after-@@LPIC+ecx],esp
- pop es
-{$else darwin}
- add ecx,@_GLOBAL_OFFSET_TABLE_
- mov [ecx].OFFSET before,esp
- push es
- mov [ecx].OFFSET after,esp
- pop es
-{$endif darwin}
-{$endif not FPC_PIC}
end;
- Writeln('Intel "push es" uses ',before-after,' bytes');
-{$endif CPUI386}
+ Writeln('Intel "push es" uses ',lpush,' bytes');
if haserror then
Halt(1);
+end;
+
+begin
+ dotest;
end.
diff --git a/mips/tests/test/testsse2.pp b/mips/tests/test/testsse2.pp
index e6ecd81ad9..5ad9cb0d30 100644
--- a/mips/tests/test/testsse2.pp
+++ b/mips/tests/test/testsse2.pp
@@ -22,7 +22,7 @@ begin
psubq %xmm1,%xmm2
psubq q-.LPIC(%ecx),%xmm4
{$else darwin}
- addl $_GLOBAL_OFFSET_TABLE_,%ecx
+ addl $_GLOBAL_OFFSET_TABLE_+1,%ecx
movdqa %xmm1,%xmm2
movdqa q@GOT(%ecx),%xmm4
psubq %xmm1,%xmm2
diff --git a/mips/tests/test/tgeneric76.pp b/mips/tests/test/tgeneric76.pp
new file mode 100644
index 0000000000..4b2aa6ef6e
--- /dev/null
+++ b/mips/tests/test/tgeneric76.pp
@@ -0,0 +1,45 @@
+{$mode delphi}
+
+unit tgeneric76;
+
+interface
+
+type
+
+ { TPointEx }
+
+ TPointEx<T> = record
+ X, Y: T;
+ function Create(const AX, AY: T): TPointEx<T>;
+ class procedure Swap(var A, B: TPointEx<T>); static;
+ class procedure OrderByY(var A, B: TPointEx<T>); static;
+ end;
+
+ TPoint = TPointEx<integer>;
+ TPointF = TPointEx<single>;
+
+implementation
+
+function TPointEx<T>.Create(const AX, AY: T): TPointEx<T>;
+begin
+ result.X:=AX;
+ result.Y:=AY;
+end;
+
+class procedure TPointEx<T>.Swap(var A, B: TPointEx<T>);
+var
+ tmp: TPointEx<T>;
+begin
+ tmp:=A;
+ A:=B;
+ B:=tmp;
+end;
+
+class procedure TPointEx<T>.OrderByY(var A, B: TPointEx<T>);
+begin
+ if A.Y > B.Y then
+ TPointEx<T>.Swap(A,B);
+end;
+
+
+end.
diff --git a/mips/tests/test/tgeneric77.pp b/mips/tests/test/tgeneric77.pp
new file mode 100644
index 0000000000..060c802d37
--- /dev/null
+++ b/mips/tests/test/tgeneric77.pp
@@ -0,0 +1,48 @@
+{$mode objfpc}{$h+}
+{$modeswitch advancedrecords}
+
+unit tgeneric77;
+
+interface
+
+type
+
+ { TPointEx }
+
+ generic TPointEx<T> = record
+ X, Y: T;
+ function Create(const AX, AY: T): TPointEx;
+ class procedure Swap(var A, B: TPointEx); static;
+ class procedure OrderByY(var A, B: TPointEx); static;
+ end;
+
+ //TPoint = specialize TPointEx<integer>;
+ TPointF = specialize TPointEx<single>;
+
+implementation
+
+{ TPoint<T> }
+
+function TPointEx.Create(const AX, AY: T): TPointEx;
+begin
+ result.X:=AX;
+ result.Y:=AY;
+end;
+
+class procedure TPointEx.Swap(var A, B: TPointEx);
+var
+ tmp: TPointEx;
+begin
+ tmp:=A;
+ A:=B;
+ B:=tmp;
+end;
+
+class procedure TPointEx.OrderByY(var A, B: TPointEx);
+begin
+ if A.Y > B.Y then
+ TPointEx.Swap(A,B);
+end;
+
+
+end.
diff --git a/mips/tests/test/tgeneric78.pp b/mips/tests/test/tgeneric78.pp
new file mode 100644
index 0000000000..4addc2b12e
--- /dev/null
+++ b/mips/tests/test/tgeneric78.pp
@@ -0,0 +1,27 @@
+{ %NORUN }
+
+{ additional test based on 21064 }
+program tgeneric78;
+
+{$mode delphi}
+
+type
+ IGenericIntf<T> = interface
+ function SomeMethod: T;
+ end;
+
+ TGenericClass<T> = class(TInterfacedObject, IGenericIntf<LongInt>)
+ private
+ protected
+ function GenericIntf_SomeMethod: LongInt;
+ function IGenericIntf<LongInt>.SomeMethod = GenericIntf_SomeMethod;
+ end;
+
+function TGenericClass<T>.GenericIntf_SomeMethod: LongInt;
+begin
+end;
+
+type
+ TGenericClassLongInt = TGenericClass<String>;
+begin
+end.
diff --git a/mips/tests/test/tgeneric79.pp b/mips/tests/test/tgeneric79.pp
new file mode 100644
index 0000000000..da94c73e20
--- /dev/null
+++ b/mips/tests/test/tgeneric79.pp
@@ -0,0 +1,27 @@
+{ %NORUN }
+
+{ additional test based on 21064 }
+program tgeneric79;
+
+{$mode objfpc}
+
+type
+ generic IGenericIntf<T> = interface
+ function SomeMethod: T;
+ end;
+
+ generic TGenericClass<T> = class(TInterfacedObject, specialize IGenericIntf<LongInt>)
+ private
+ protected
+ function GenericIntf_SomeMethod: LongInt;
+ function IGenericIntf<LongInt>.SomeMethod = GenericIntf_SomeMethod;
+ end;
+
+function TGenericClass.GenericIntf_SomeMethod: LongInt;
+begin
+end;
+
+type
+ TGenericClassLongInt = specialize TGenericClass<String>;
+begin
+end.
diff --git a/mips/tests/test/tgeneric80.pp b/mips/tests/test/tgeneric80.pp
new file mode 100644
index 0000000000..f23c900dc1
--- /dev/null
+++ b/mips/tests/test/tgeneric80.pp
@@ -0,0 +1,18 @@
+{ %NORUN }
+
+program tgeneric80;
+
+{$mode delphi}
+
+type
+ TTest<T, S> = record
+ end;
+ TTest<T> = record
+ end;
+ PTest = ^TTest;
+ TTest = record
+ end;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric81.pp b/mips/tests/test/tgeneric81.pp
new file mode 100644
index 0000000000..8618e9ad39
--- /dev/null
+++ b/mips/tests/test/tgeneric81.pp
@@ -0,0 +1,18 @@
+{ %NORUN }
+
+program tgeneric81;
+
+{$mode delphi}
+
+type
+ PTest = ^TTest;
+ TTest<T, S> = record
+ end;
+ TTest<T> = record
+ end;
+ TTest = record
+ end;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric82.pp b/mips/tests/test/tgeneric82.pp
new file mode 100644
index 0000000000..7b556ce0f7
--- /dev/null
+++ b/mips/tests/test/tgeneric82.pp
@@ -0,0 +1,18 @@
+{ %NORUN }
+
+program tgeneric82;
+
+{$mode delphi}
+
+type
+ TTest = record
+ end;
+ TTest<T, S> = record
+ end;
+ TTest<T> = record
+ end;
+ PTest = ^TTest;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric83.pp b/mips/tests/test/tgeneric83.pp
new file mode 100644
index 0000000000..0e081956fd
--- /dev/null
+++ b/mips/tests/test/tgeneric83.pp
@@ -0,0 +1,16 @@
+{ %FAIL }
+
+program tgeneric83;
+
+{$mode delphi}
+
+type
+ TTest<T> = record
+ end;
+
+const
+ Test: ^TTest = Nil;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric84.pp b/mips/tests/test/tgeneric84.pp
new file mode 100644
index 0000000000..ec33dd07a1
--- /dev/null
+++ b/mips/tests/test/tgeneric84.pp
@@ -0,0 +1,14 @@
+{ %FAIL }
+
+program tgeneric84;
+
+{$mode objfpc}
+
+type
+ generic TTest<T> = record
+ end;
+
+ PTest = ^TTest;
+
+begin
+end.
diff --git a/mips/tests/test/tgeneric85.pp b/mips/tests/test/tgeneric85.pp
new file mode 100644
index 0000000000..e7c634560f
--- /dev/null
+++ b/mips/tests/test/tgeneric85.pp
@@ -0,0 +1,16 @@
+{ %FAIL }
+
+program tgeneric85;
+
+{$mode objfpc}
+
+type
+ generic TTest<T> = record
+ end;
+
+const
+ Test: ^TTest = Nil;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric86.pp b/mips/tests/test/tgeneric86.pp
new file mode 100644
index 0000000000..02520a0f41
--- /dev/null
+++ b/mips/tests/test/tgeneric86.pp
@@ -0,0 +1,17 @@
+{ %NORUN }
+
+program tgeneric86;
+
+{$mode objfpc}{$H+}
+{$modeswitch advancedrecords}
+
+type
+ generic TTest<T> = record
+ type
+ PTest = ^TTest;
+ end;
+
+begin
+
+end.
+
diff --git a/mips/tests/test/tgeneric87.pp b/mips/tests/test/tgeneric87.pp
new file mode 100644
index 0000000000..33e2afc92c
--- /dev/null
+++ b/mips/tests/test/tgeneric87.pp
@@ -0,0 +1,18 @@
+{ %FAIL }
+
+program tgeneric87;
+
+{$mode objfpc}
+
+type
+ generic TTest<T> = record
+
+ end;
+
+const
+ TestLongIntNil: ^specialize TTest<LongInt> = Nil;
+ TestBooleanNil: ^specialize TTest<Boolean> = Nil;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric88.pp b/mips/tests/test/tgeneric88.pp
new file mode 100644
index 0000000000..c8233ee7e2
--- /dev/null
+++ b/mips/tests/test/tgeneric88.pp
@@ -0,0 +1,17 @@
+{ %FAIL }
+
+program tgeneric88;
+
+{$mode objfpc}
+
+type
+ generic TTest<T> = record
+
+ end;
+
+ PTestLongInt = ^specialize TTest<LongInt>;
+ PTestBoolean = ^specialize TTest<Boolean>;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric89.pp b/mips/tests/test/tgeneric89.pp
new file mode 100644
index 0000000000..5e50ef1549
--- /dev/null
+++ b/mips/tests/test/tgeneric89.pp
@@ -0,0 +1,17 @@
+{ %NORUN }
+
+program tgeneric89;
+
+{$mode delphi}
+
+type
+ TTest<T> = record
+
+ end;
+
+ PTestLongInt = ^TTest<LongInt>;
+ PTestBoolean = ^TTest<Boolean>;
+
+begin
+
+end.
diff --git a/mips/tests/test/tgeneric90.pp b/mips/tests/test/tgeneric90.pp
new file mode 100644
index 0000000000..0c9ae3c4cb
--- /dev/null
+++ b/mips/tests/test/tgeneric90.pp
@@ -0,0 +1,26 @@
+{ %NORUN }
+
+program tgeneric90;
+
+{$mode delphi}
+
+type
+ TTest = record
+
+ end;
+
+ TTest<T> = record
+
+ end;
+
+ TTest<T, S> = record
+
+ end;
+
+ PTestLongInt = ^TTest<LongInt>;
+ PTestLongIntLongInt = ^TTest<LongInt, LongInt>;
+ PTest = ^TTest;
+
+begin
+
+end.
diff --git a/mips/tests/test/tint642.pp b/mips/tests/test/tint642.pp
index 7beab28039..c60ab52a3b 100644
--- a/mips/tests/test/tint642.pp
+++ b/mips/tests/test/tint642.pp
@@ -248,6 +248,8 @@ procedure testshlshrqword;
l1:=16;
l2:=0;
+ if (q1 shl 0)<>q1 then
+ do_error(1499);
if (q1 shl 16)<>q3 then
do_error(1500);
if (q1 shl 48)<>q0 then
@@ -277,6 +279,8 @@ procedure testshlshrqword;
if ((q1+q0) shl (l1+l2))<>q3 then
do_error(1509);
+ if (q1 shr 0)<>q1 then
+ do_error(15091);
if (q1 shr 16)<>q2 then
do_error(1510);
if (q1 shr 48)<>q0 then
diff --git a/mips/tests/test/trhlp44.pp b/mips/tests/test/trhlp44.pp
new file mode 100644
index 0000000000..4c4951ec3b
--- /dev/null
+++ b/mips/tests/test/trhlp44.pp
@@ -0,0 +1,31 @@
+{ %NORUN }
+
+program trhlp44;
+
+{$mode delphi}
+
+type
+ TTest = record
+
+ end;
+
+ TTestHelper = record helper for TTest
+ procedure SayHello(const I: Integer); overload;
+ procedure SayHello(const S: string); overload;
+ end;
+
+procedure TTestHelper.SayHello(const I: Integer); overload;
+begin
+ Writeln('Hello ', I);
+end;
+
+procedure TTestHelper.SayHello(const S: string); overload;
+begin
+ Writeln('Hello ', S);
+end;
+
+var
+ Obj: TTest;
+begin
+ Obj.SayHello('FPC');
+end.
diff --git a/mips/tests/webtbf/tw22219.pp b/mips/tests/webtbf/tw22219.pp
new file mode 100644
index 0000000000..fa805dffa6
--- /dev/null
+++ b/mips/tests/webtbf/tw22219.pp
@@ -0,0 +1,16 @@
+{ %FAIL }
+
+program tw22219;
+{$MODE DELPHI}
+
+type
+ TWrapper<P, Q> = record end;
+ TWrapper<R> = record end;
+ AmbiguousPointer = ^TWrapper;
+
+var
+ Z: AmbiguousPointer;
+
+begin
+
+end.
diff --git a/mips/tests/webtbs/tw20947.pp b/mips/tests/webtbs/tw20947.pp
new file mode 100644
index 0000000000..b2d3ac7675
--- /dev/null
+++ b/mips/tests/webtbs/tw20947.pp
@@ -0,0 +1,21 @@
+{ the important part of this test is a cross compilation which a change in the
+ size of the bitness, e.g. from Win32 to Win64 where the unit "fgl" was
+ compiled with the 32-to-64-bit cross compiler and this program itself is
+ compiled with the native 64-bit compiler }
+
+program tw20947;
+
+uses
+ fgl;
+
+type
+ TTestList = specialize TFPGList<Byte>;
+
+Var
+ Test : TTestList;
+begin
+ Test := TTestList.Create;
+ Test.Add(2);
+ WriteLn(Test[0]); // This should output 2 to console
+ Test.Free;
+end.
diff --git a/mips/tests/webtbs/tw20998.pp b/mips/tests/webtbs/tw20998.pp
index 92b6f93d15..6ee9ea7cbf 100644
--- a/mips/tests/webtbs/tw20998.pp
+++ b/mips/tests/webtbs/tw20998.pp
@@ -1,18 +1,23 @@
var
i : int64;
-
+ j, k: longint;
begin
- i:=6400;
- i:=i div 64;
- if i<>100 then
- halt(1);
+ k:=64;
+ for j:=6400 to 6464 do
+ begin
+ i:=j;
+ if (i div 64) <> (i div k) then
+ halt(1);
+ end;
i:=6500;
i:=i div 65;
if i<>100 then
halt(1);
- i:=-6400;
- i:=i div 64;
- if i<>-100 then
- halt(1);
+ for j:=-6400 downto -6464 do
+ begin
+ i:=j;
+ if (i div 64) <> (i div k) then
+ halt(2);
+ end;
writeln('ok');
end.
diff --git a/mips/tests/webtbs/tw21064a.pp b/mips/tests/webtbs/tw21064a.pp
new file mode 100644
index 0000000000..e813aab427
--- /dev/null
+++ b/mips/tests/webtbs/tw21064a.pp
@@ -0,0 +1,26 @@
+{ %NORUN }
+
+program tw21064a;
+
+{$mode delphi}
+
+type
+ IGenericIntf<T> = interface
+ function SomeMethod: T;
+ end;
+
+ TGenericClass<T> = class(TInterfacedObject, IGenericIntf<T>)
+ private
+ protected
+ function GenericIntf_SomeMethod: T;
+ function IGenericIntf<T>.SomeMethod = GenericIntf_SomeMethod;
+ end;
+
+function TGenericClass<T>.GenericIntf_SomeMethod: T;
+begin
+end;
+
+type
+ TGenericClassLongInt = TGenericClass<LongInt>;
+begin
+end.
diff --git a/mips/tests/webtbs/tw21064b.pp b/mips/tests/webtbs/tw21064b.pp
new file mode 100644
index 0000000000..64be8cc69c
--- /dev/null
+++ b/mips/tests/webtbs/tw21064b.pp
@@ -0,0 +1,28 @@
+{ %NORUN }
+
+program tw21064b;
+
+{$mode delphi}
+
+type
+ IGenericIntf<T> = interface
+ function SomeMethod: T;
+ end;
+
+ TGenericClass<T> = class(TInterfacedObject, IGenericIntf<T>)
+ private
+ type
+ IntfType = IGenericIntf<T>;
+ protected
+ function GenericIntf_SomeMethod: T;
+ function IntfType.SomeMethod = GenericIntf_SomeMethod;
+ end;
+
+function TGenericClass<T>.GenericIntf_SomeMethod: T;
+begin
+end;
+
+type
+ TGenericClassLongInt = TGenericClass<LongInt>;
+begin
+end.
diff --git a/mips/tests/webtbs/tw21350a.pp b/mips/tests/webtbs/tw21350a.pp
new file mode 100644
index 0000000000..a67d6b3997
--- /dev/null
+++ b/mips/tests/webtbs/tw21350a.pp
@@ -0,0 +1,45 @@
+{$mode delphi}
+
+unit tw21350a;
+
+interface
+
+type
+
+ { TPointEx }
+
+ TPointEx<T> = object
+ X, Y: T;
+ function Create(const AX, AY: T): TPointEx<T>;
+ class procedure Swap(var A, B: TPointEx<T>); static;
+ class procedure OrderByY(var A, B: TPointEx<T>); static;
+ end;
+
+ TPoint = TPointEx<integer>;
+ TPointF = TPointEx<single>;
+
+implementation
+
+function TPointEx<T>.Create(const AX, AY: T): TPointEx<T>;
+begin
+ result.X:=AX;
+ result.Y:=AY;
+end;
+
+class procedure TPointEx<T>.Swap(var A, B: TPointEx<T>);
+var
+ tmp: TPointEx<T>;
+begin
+ tmp:=A;
+ A:=B;
+ B:=tmp;
+end;
+
+class procedure TPointEx<T>.OrderByY(var A, B: TPointEx<T>);
+begin
+ if A.Y > B.Y then
+ TPointEx<T>.Swap(A,B);
+end;
+
+
+end.
diff --git a/mips/tests/webtbs/tw21350b.pp b/mips/tests/webtbs/tw21350b.pp
new file mode 100644
index 0000000000..5aefe310db
--- /dev/null
+++ b/mips/tests/webtbs/tw21350b.pp
@@ -0,0 +1,47 @@
+{$mode objfpc}{$h+}
+
+unit tw21350b;
+
+interface
+
+type
+
+ { TPointEx }
+
+ generic TPointEx<T> = object
+ X, Y: T;
+ function Create(const AX, AY: T): TPointEx;
+ class procedure Swap(var A, B: TPointEx); static;
+ class procedure OrderByY(var A, B: TPointEx); static;
+ end;
+
+ //TPoint = specialize TPointEx<integer>;
+ TPointF = specialize TPointEx<single>;
+
+implementation
+
+{ TPoint<T> }
+
+function TPointEx.Create(const AX, AY: T): TPointEx;
+begin
+ result.X:=AX;
+ result.Y:=AY;
+end;
+
+class procedure TPointEx.Swap(var A, B: TPointEx);
+var
+ tmp: TPointEx;
+begin
+ tmp:=A;
+ A:=B;
+ B:=tmp;
+end;
+
+class procedure TPointEx.OrderByY(var A, B: TPointEx);
+begin
+ if A.Y > B.Y then
+ TPointEx.Swap(A,B);
+end;
+
+
+end.
diff --git a/mips/tests/webtbs/tw21457.pp b/mips/tests/webtbs/tw21457.pp
new file mode 100644
index 0000000000..efde6895ac
--- /dev/null
+++ b/mips/tests/webtbs/tw21457.pp
@@ -0,0 +1,24 @@
+unit tw21457;
+{$mode objfpc}
+interface
+uses Classes;
+
+Type
+ TFileStreamHelper = class helper for TFileStream
+ public
+ constructor CreateRetry(const AFileName: string; Mode: Word; Rights: Cardinal);
+ end;
+
+
+implementation
+
+{ TFileStreamHelper }
+
+constructor TFileStreamHelper.CreateRetry(const AFileName:string; Mode:Word; Rights: Cardinal);
+begin
+ //TODO
+ //=> internal error 200305103
+end;
+
+
+end.
diff --git a/mips/tests/webtbs/tw21921.pp b/mips/tests/webtbs/tw21921.pp
new file mode 100644
index 0000000000..8ed4924b97
--- /dev/null
+++ b/mips/tests/webtbs/tw21921.pp
@@ -0,0 +1,28 @@
+{ %NORUN }
+
+program tw21921;
+
+{$mode Delphi}{$H+}
+
+type
+
+ { THashEntry }
+
+ THashEntry<T> = record
+ Key: string;
+ Value: T;
+ class function Create(const AKey: string; const AValue: T): THashEntry<T>; static; inline;
+ end;
+
+class function THashEntry<T>.Create(const AKey: string; const AValue: T): THashEntry<T>;
+begin
+ Result.Key := AKey;
+ Result.Value := AValue;
+end;
+
+var
+ Entry: THashEntry<Integer>;
+begin
+ Entry := THashEntry<Integer>.Create('One', 1);
+end.
+
diff --git a/mips/tests/webtbs/tw22154.pp b/mips/tests/webtbs/tw22154.pp
new file mode 100644
index 0000000000..775c14b562
--- /dev/null
+++ b/mips/tests/webtbs/tw22154.pp
@@ -0,0 +1,18 @@
+program tw22154;
+
+{$MODE DELPHI}
+
+type
+ TWrapper<T> = class
+ procedure Z;
+ end;
+
+procedure TWrapper<T>.Z;
+const
+ A0: array [0..0] of Integer = (0); { OK }
+ A1: array [0..1] of Integer = (0, 1); { Comma not exepcted }
+begin
+end;
+
+begin
+end.
diff --git a/mips/tests/webtbs/tw22320.pp b/mips/tests/webtbs/tw22320.pp
new file mode 100644
index 0000000000..1d5752cf3b
--- /dev/null
+++ b/mips/tests/webtbs/tw22320.pp
@@ -0,0 +1,73 @@
+program Test;
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+
+{$APPTYPE CONSOLE}
+
+type
+ TwbSignature = array[0..3] of AnsiChar;
+
+ TwbConflictPriority = (
+ cpIgnore,
+ cpBenign,
+ cpTranslate,
+ cpNormal,
+ cpCritical,
+ cpFormID
+ );
+
+ IwbElement = interface
+ ['{F4B4637D-C794-415F-B5C7-587EAA4095B3}']
+ end;
+
+ TwbDontShowCallback = function(const aElement: IwbElement): Boolean;
+
+ IwbSubRecordDef = interface
+ ['{D848E426-8768-45F4-B192-4DEFBE34D40A}']
+ end;
+
+ IwbByteArrayDef = interface
+ ['{3069E1AC-4307-421B-93E4-797E18075EF9}']
+ end;
+
+function wbByteArray(const aName : string = 'Unknown';
+ aSize : Cardinal = 0;
+ aPriority : TwbConflictPriority = cpNormal;
+ aRequired : Boolean = False;
+ aDontShow : TwbDontShowCallback = nil)
+ : IwbByteArrayDef; overload;
+begin
+ Result := nil;
+end;
+
+function wbByteArray(const aSignature : TwbSignature;
+ const aName : string = 'Unknown';
+ aSize : Cardinal = 0;
+ aPriority : TwbConflictPriority = cpNormal;
+ aRequired : Boolean = False;
+ aSizeMatch : Boolean = False;
+ aDontShow : TwbDontShowCallback = nil)
+ : IwbSubRecordDef; overload;
+begin
+ Result := nil;
+ halt(2);
+end;
+
+function wbUnknown(aPriority : TwbConflictPriority = cpNormal;
+ aRequired : Boolean = False;
+ aDontShow : TwbDontShowCallback = nil)
+ : IwbByteArrayDef;
+begin
+ Result := wbByteArray('Unknown', 0, aPriority, aRequired, aDontShow);
+end;
+
+function cb(const aElement: IwbElement): Boolean;
+begin
+ halt(1);
+end;
+
+begin
+ wbUnknown(cpNormal,False,cb);
+end.
diff --git a/mips/tests/webtbs/tw22326.pp b/mips/tests/webtbs/tw22326.pp
new file mode 100644
index 0000000000..9ff1416934
--- /dev/null
+++ b/mips/tests/webtbs/tw22326.pp
@@ -0,0 +1,9 @@
+var
+ q1: QWord;
+begin
+ q1:=$1020304050607080;
+ if (q1 shl 0) <> q1 then
+ halt(1);
+ if (q1 shr 0) <> q1 then
+ halt(2);
+end.
diff --git a/mips/tests/webtbs/tw22329.pp b/mips/tests/webtbs/tw22329.pp
new file mode 100644
index 0000000000..81a9ec9dc3
--- /dev/null
+++ b/mips/tests/webtbs/tw22329.pp
@@ -0,0 +1,32 @@
+{ %NORUN }
+
+program tw22329;
+
+{$mode delphi}
+
+type
+ TObjectHelper = class helper for TObject
+ procedure SayHello(const I: Integer); overload;
+ procedure SayHello(const S: string); overload;
+ end;
+
+procedure TObjectHelper.SayHello(const I: Integer); overload;
+begin
+ Writeln('Hello ', I);
+end;
+
+procedure TObjectHelper.SayHello(const S: string); overload;
+begin
+ Writeln('Hello ', S);
+end;
+
+var
+ Obj: TObject;
+begin
+ Obj := TObject.Create;
+ try
+ Obj.SayHello('FPC');
+ finally
+ Obj.Free;
+ end;
+end.
diff --git a/mips/tests/webtbs/tw22331.pp b/mips/tests/webtbs/tw22331.pp
new file mode 100644
index 0000000000..01c1485e6c
--- /dev/null
+++ b/mips/tests/webtbs/tw22331.pp
@@ -0,0 +1,139 @@
+procedure X;
+var
+ w, h: integer;
+begin
+ w:=1;
+ h:=2;
+ writeln(round(w / 2 - 0), round(h - 0));
+ writeln(round(w / 2 - 138.809093), round(h - 661.165204));
+ writeln(round(w / 2 - 138.683051), round(h - 661.003245));
+ writeln(round(w / 2 - 138.556540), round(h - 660.840685));
+ writeln(round(w / 2 - 138.429558), round(h - 660.677449));
+ writeln(round(w / 2 - 138.302098), round(h - 660.513612));
+ writeln(round(w / 2 - 138.174178), round(h - 660.349250));
+ writeln(round(w / 2 - 138.045779), round(h - 660.184211));
+ writeln(round(w / 2 - 137.916911), round(h - 660.018571));
+ writeln(round(w / 2 - 137.787573), round(h - 659.852405));
+ writeln(round(w / 2 - 137.657765), round(h - 659.685563));
+ writeln(round(w / 2 - 137.527488), round(h - 659.518121));
+ writeln(round(w / 2 - 137.396732), round(h - 659.350077));
+ writeln(round(w / 2 - 137.265516), round(h - 659.181432));
+ writeln(round(w / 2 - 137.133821), round(h - 659.012187));
+ writeln(round(w / 2 - 137.001656), round(h - 658.842340));
+ writeln(round(w / 2 - 136.869023), round(h - 658.671892));
+ writeln(round(w / 2 - 136.735910), round(h - 658.500844));
+ writeln(round(w / 2 - 136.602337), round(h - 658.329119));
+ writeln(round(w / 2 - 136.468294), round(h - 658.156944));
+ writeln(round(w / 2 - 136.333773), round(h - 657.984017));
+ writeln(round(w / 2 - 136.198782), round(h - 657.810490));
+ writeln(round(w / 2 - 136.063322), round(h - 657.636437));
+ writeln(round(w / 2 - 135.927392), round(h - 657.461782));
+ writeln(round(w / 2 - 135.790993), round(h - 657.286452));
+ writeln(round(w / 2 - 135.654114), round(h - 657.110521));
+ writeln(round(w / 2 - 135.516776), round(h - 656.933988));
+ writeln(round(w / 2 - 135.378959), round(h - 656.756930));
+ writeln(round(w / 2 - 135.240672), round(h - 656.579196));
+ writeln(round(w / 2 - 135.101916), round(h - 656.400936));
+ writeln(round(w / 2 - 134.962690), round(h - 656.222000));
+ writeln(round(w / 2 - 134.822995), round(h - 656.042463));
+ writeln(round(w / 2 - 134.682821), round(h - 655.862325));
+ writeln(round(w / 2 - 134.542186), round(h - 655.681586));
+ writeln(round(w / 2 - 134.147430), round(h - 655.174225));
+ writeln(round(w / 2 - 134.006815), round(h - 654.993486));
+ writeln(round(w / 2 - 133.866669), round(h - 654.813348));
+ writeln(round(w / 2 - 133.727002), round(h - 654.633886));
+ writeln(round(w / 2 - 133.607551), round(h - 654.480415));
+ writeln(round(w / 2 - 133.488777), round(h - 654.287807));
+ writeln(round(w / 2 - 133.370406), round(h - 654.095800));
+ writeln(round(w / 2 - 133.252440), round(h - 653.904469));
+ writeln(round(w / 2 - 133.134877), round(h - 653.713814));
+ writeln(round(w / 2 - 133.017708), round(h - 653.523836));
+ writeln(round(w / 2 - 132.900953), round(h - 653.334458));
+ writeln(round(w / 2 - 132.784592), round(h - 653.145756));
+ writeln(round(w / 2 - 132.668644), round(h - 652.957730));
+ writeln(round(w / 2 - 132.553090), round(h - 652.770306));
+ writeln(round(w / 2 - 132.437940), round(h - 652.583557));
+ writeln(round(w / 2 - 132.323204), round(h - 652.397485));
+ writeln(round(w / 2 - 132.208862), round(h - 652.212088));
+ writeln(round(w / 2 - 132.094923), round(h - 652.027293));
+ writeln(round(w / 2 - 131.981379), round(h - 651.843098));
+ writeln(round(w / 2 - 131.868248), round(h - 651.659655));
+ writeln(round(w / 2 - 131.755521), round(h - 651.476812));
+ writeln(round(w / 2 - 131.643198), round(h - 651.294721));
+ writeln(round(w / 2 - 131.531269), round(h - 651.113231));
+ writeln(round(w / 2 - 131.419753), round(h - 650.932342));
+ writeln(round(w / 2 - 131.308631), round(h - 650.752129));
+ writeln(round(w / 2 - 131.197914), round(h - 650.572516));
+ writeln(round(w / 2 - 131.087609), round(h - 650.393655));
+ writeln(round(w / 2 - 130.977699), round(h - 650.215395));
+ writeln(round(w / 2 - 130.868193), round(h - 650.037812));
+ writeln(round(w / 2 - 130.759090), round(h - 649.860904));
+ writeln(round(w / 2 - 130.650391), round(h - 649.684597));
+ writeln(round(w / 2 - 130.542087), round(h - 649.508966));
+ writeln(round(w / 2 - 130.434196), round(h - 649.334011));
+ writeln(round(w / 2 - 130.326708), round(h - 649.159657));
+ writeln(round(w / 2 - 130.219615), round(h - 648.985980));
+ writeln(round(w / 2 - 130.112935), round(h - 648.813053));
+ writeln(round(w / 2 - 130.006650), round(h - 648.640577));
+ writeln(round(w / 2 - 129.900768), round(h - 648.468928));
+ writeln(round(w / 2 - 129.795290), round(h - 648.297879));
+ writeln(round(w / 2 - 129.690215), round(h - 648.127507));
+ writeln(round(w / 2 - 129.585554), round(h - 647.957735));
+ writeln(round(w / 2 - 129.481278), round(h - 647.788565));
+ writeln(round(w / 2 - 129.377415), round(h - 647.620146));
+ writeln(round(w / 2 - 129.273956), round(h - 647.452402));
+ writeln(round(w / 2 - 129.170901), round(h - 647.285260));
+ writeln(round(w / 2 - 129.068240), round(h - 647.118794));
+ writeln(round(w / 2 - 128.965992), round(h - 646.952929));
+ writeln(round(w / 2 - 128.864138), round(h - 646.787815));
+ writeln(round(w / 2 - 128.762689), round(h - 646.623302));
+ writeln(round(w / 2 - 128.661652), round(h - 646.459390));
+ writeln(round(w / 2 - 128.561010), round(h - 646.296154));
+ writeln(round(w / 2 - 128.460771), round(h - 646.133594));
+ writeln(round(w / 2 - 128.360937), round(h - 645.971710));
+ writeln(round(w / 2 - 128.261506), round(h - 645.810502));
+ writeln(round(w / 2 - 128.162469), round(h - 645.649895));
+ writeln(round(w / 2 - 128.063846), round(h - 645.489889));
+ writeln(round(w / 2 - 127.965627), round(h - 645.330635));
+ writeln(round(w / 2 - 127.894723), round(h - 645.215626));
+ writeln(round(w / 2 - 127.808626), round(h - 645.050587));
+ writeln(round(w / 2 - 127.722895), round(h - 644.886149));
+ writeln(round(w / 2 - 127.637511), round(h - 644.722462));
+ writeln(round(w / 2 - 127.552485), round(h - 644.559452));
+ writeln(round(w / 2 - 127.467815), round(h - 644.397042));
+ writeln(round(w / 2 - 127.383502), round(h - 644.235383));
+ writeln(round(w / 2 - 127.299537), round(h - 644.074476));
+ writeln(round(w / 2 - 127.215937), round(h - 643.914170));
+ writeln(round(w / 2 - 127.132695), round(h - 643.754540));
+ writeln(round(w / 2 - 127.049800), round(h - 643.595585));
+ writeln(round(w / 2 - 126.967261), round(h - 643.437307));
+ writeln(round(w / 2 - 126.885080), round(h - 643.279780));
+ writeln(round(w / 2 - 126.803255), round(h - 643.122854));
+ writeln(round(w / 2 - 126.721788), round(h - 642.966680));
+ writeln(round(w / 2 - 126.640677), round(h - 642.811106));
+ writeln(round(w / 2 - 126.559923), round(h - 642.656359));
+ writeln(round(w / 2 - 126.479516), round(h - 642.502137));
+ writeln(round(w / 2 - 126.399475), round(h - 642.348667));
+ writeln(round(w / 2 - 126.319782), round(h - 642.195872));
+ writeln(round(w / 2 - 126.240446), round(h - 642.043754));
+ writeln(round(w / 2 - 126.161467), round(h - 641.892312));
+ writeln(round(w / 2 - 126.082844), round(h - 641.741546));
+ writeln(round(w / 2 - 126.004578), round(h - 641.591456));
+ writeln(round(w / 2 - 125.926669), round(h - 641.442117));
+ writeln(round(w / 2 - 125.849108), round(h - 641.293379));
+ writeln(round(w / 2 - 125.771913), round(h - 641.145393));
+ writeln(round(w / 2 - 125.695065), round(h - 640.998007));
+ writeln(round(w / 2 - 125.618583), round(h - 640.851372));
+ writeln(round(w / 2 - 125.542449), round(h - 640.705414));
+ writeln(round(w / 2 - 125.466671), round(h - 640.560132));
+ writeln(round(w / 2 - 125.391251), round(h - 640.415525));
+ writeln(round(w / 2 - 125.316178), round(h - 640.271595));
+ writeln(round(w / 2 - 125.241471), round(h - 640.128341));
+ writeln(round(w / 2 - 125.167121), round(h - 639.985763));
+ writeln(round(w / 2 - 125.093118), round(h - 639.843861));
+ writeln(round(w / 2 - 125.019472), round(h - 639.702711));
+ writeln(round(w / 2 - 124.873260), round(h - 639.422287));
+end;
+begin
+ X
+end.
diff --git a/mips/tests/webtbs/tw22344.pp b/mips/tests/webtbs/tw22344.pp
new file mode 100644
index 0000000000..a20b70ab17
--- /dev/null
+++ b/mips/tests/webtbs/tw22344.pp
@@ -0,0 +1,24 @@
+program showbug ;
+
+{$mode macpas}
+
+var
+ glob: integer;
+
+function countchars: INTEGER ;
+begin
+ countchars:=255;
+ if glob=5 then
+ countchars := 0
+ else
+ begin
+ inc(glob);
+ countchars := 1 + countchars
+ end
+ end;
+
+begin
+ if countchars<>5 then
+ halt(1);
+end .
+