diff --git a/Compiler b/Compiler index 8878691..a865f8d 100644 Binary files a/Compiler and b/Compiler differ diff --git a/Compiler.exe b/Compiler.exe index 0f70e86..9177679 100644 Binary files a/Compiler.exe and b/Compiler.exe differ diff --git a/doc/x86.txt b/doc/x86.txt index 9680a3e..ac90f51 100644 --- a/doc/x86.txt +++ b/doc/x86.txt @@ -208,7 +208,7 @@ UTF-8 с BOM-сигнатурой. При объявлении процедурных типов и глобальных процедур, после ключевого слова PROCEDURE может быть указан флаг соглашения о вызове: [stdcall], -[cdecl], [ccall], [windows], [linux], [oberon]. Например: +[cdecl], [fastcall], [ccall], [windows], [linux], [oberon]. Например: PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; diff --git a/source/ERRORS.ob07 b/source/ERRORS.ob07 index c9056bd..ca95f1e 100644 --- a/source/ERRORS.ob07 +++ b/source/ERRORS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2021, Anton Krotov + Copyright (c) 2018-2022, Anton Krotov All rights reserved. *) @@ -154,6 +154,7 @@ BEGIN |123: str := "illegal flag" |124: str := "unknown flag" |125: str := "flag not supported" + |126: str := "type of formal parameter should not be REAL" END; C.StringLn(str); C.String(" file: "); C.StringLn(fname); diff --git a/source/IL.ob07 b/source/IL.ob07 index e7033b3..aa9c94b 100644 --- a/source/IL.ob07 +++ b/source/IL.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2021, Anton Krotov + Copyright (c) 2018-2022, Anton Krotov All rights reserved. *) @@ -15,6 +15,8 @@ CONST call_stack* = 0; call_win64* = 1; call_sysv* = 2; + call_fast1* = 3; + call_fast2* = 4; begin_loop* = 1; end_loop* = 2; @@ -80,7 +82,7 @@ CONST opTYPEGD* = 207; opCALLI* = 208; opPUSHIP* = 209; opSAVEIP* = 210; opEQIP* = 211; opNEIP* = 212; opSAVE16C* = 213; opWCHR* = 214; opHANDLER* = 215; - opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; + opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; opFASTCALL* = 220; opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4; @@ -800,8 +802,21 @@ BEGIN END LeaveC; +PROCEDURE fastcall (VAR callconv: INTEGER); +BEGIN + IF callconv = call_fast1 THEN + AddCmd(opFASTCALL, 1); + callconv := call_stack + ELSIF callconv = call_fast2 THEN + AddCmd(opFASTCALL, 2); + callconv := call_stack + END +END fastcall; + + PROCEDURE Call* (proc, callconv, fparams: INTEGER); BEGIN + fastcall(callconv); CASE callconv OF |call_stack: Jmp(opCALL, proc) |call_win64: Jmp(opWIN64CALL, proc) @@ -813,6 +828,7 @@ END Call; PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER); BEGIN + fastcall(callconv); CASE callconv OF |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label) |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label) @@ -824,6 +840,7 @@ END CallImp; PROCEDURE CallP* (callconv, fparams: INTEGER); BEGIN + fastcall(callconv); CASE callconv OF |call_stack: AddCmd0(opCALLP) |call_win64: AddCmd(opWIN64CALLP, fparams) diff --git a/source/PARS.ob07 b/source/PARS.ob07 index fe9a0a3..17d1ab3 100644 --- a/source/PARS.ob07 +++ b/source/PARS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2021, Anton Krotov + Copyright (c) 2018-2022, Anton Krotov All rights reserved. *) @@ -445,6 +445,7 @@ VAR vPar: BOOLEAN; dim: INTEGER; t0, t1: PROG._TYPE; + pos: POSITION; BEGIN vPar := parser.sym = SCAN.lxVAR; @@ -462,6 +463,7 @@ VAR ExpectSym(parser, SCAN.lxIDENT) ELSIF parser.sym = SCAN.lxCOLON THEN Next(parser); + getpos(parser, pos); dim := 0; WHILE parser.sym = SCAN.lxARRAY DO INC(dim); @@ -482,7 +484,9 @@ VAR t0 := t1; DEC(dim) END; - + IF _type.call IN {PROG.fastcall, PROG._fastcall} THEN + check(t1.typ # PROG.tREAL, pos, 126) + END; PROG.setParams(_type, t1); Next(parser); exit := TRUE @@ -550,6 +554,8 @@ BEGIN sf := PROG.sf_code ELSIF parser.lex.ident.s = "oberon" THEN sf := PROG.sf_oberon + ELSIF parser.lex.ident.s = "fastcall" THEN + sf := PROG.sf_fastcall ELSIF parser.lex.ident.s = "noalign" THEN sf := PROG.sf_noalign ELSE @@ -583,6 +589,8 @@ BEGIN res := PROG.systemv |PROG.sf_code: res := PROG.code + |PROG.sf_fastcall: + res := PROG.fastcall |PROG.sf_oberon: IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN res := PROG.default32 @@ -1106,6 +1114,8 @@ VAR enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc._type.parSize)) ELSIF codeProc THEN + ELSIF call IN {PROG.fastcall, PROG._fastcall} THEN + enter := IL.Enter(label, proc._type.parSize) ELSE enter := IL.Enter(label, 0) END; diff --git a/source/PROG.ob07 b/source/PROG.ob07 index 925e4e4..5147c1a 100644 --- a/source/PROG.ob07 +++ b/source/PROG.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2021, Anton Krotov + Copyright (c) 2018-2022, Anton Krotov All rights reserved. *) @@ -51,17 +51,18 @@ CONST systemv* = 14; _systemv* = systemv + 1; default16* = 16; _default16* = default16 + 1; code* = 18; _code* = code + 1; + fastcall* = 20; _fastcall* = fastcall + 1; noalign* = 22; - callee_clean_up* = {default32, _default32, stdcall, _stdcall, default64, _default64}; + callee_clean_up* = {default32, _default32, stdcall, _stdcall, default64, _default64, fastcall, _fastcall}; sf_stdcall* = 0; sf_oberon* = 1; sf_cdecl* = 2; sf_ccall* = 3; sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; - sf_code* = 8; - sf_noalign* = 9; + sf_code* = 8; sf_fastcall* = 9; + sf_noalign* = 10; - proc_flags* = {sf_stdcall, sf_cdecl, sf_ccall, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon}; + proc_flags* = {sf_stdcall, sf_cdecl, sf_ccall, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon, sf_fastcall}; rec_flags* = {sf_noalign}; STACK_FRAME = 2; @@ -1219,9 +1220,9 @@ BEGIN program.options := options; CASE TARGETS.OS OF - |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_cdecl, sf_ccall, sf_noalign} - |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_cdecl, sf_ccall, sf_noalign} - |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_cdecl, sf_ccall, sf_noalign} + |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign} + |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign} + |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign} |TARGETS.osWIN64: program.sysflags := {sf_oberon, sf_windows, sf_win64, sf_systemv, sf_ccall, sf_noalign} |TARGETS.osLINUX64: program.sysflags := {sf_oberon, sf_linux, sf_win64, sf_systemv, sf_ccall, sf_noalign} |TARGETS.osNONE: program.sysflags := {sf_code} diff --git a/source/STATEMENTS.ob07 b/source/STATEMENTS.ob07 index fcdab7d..d3d940e 100644 --- a/source/STATEMENTS.ob07 +++ b/source/STATEMENTS.ob07 @@ -1621,6 +1621,15 @@ BEGIN callconv := IL.call_sysv; fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, PROG.MAXSYSVPARAM - 1, int, flt)), 5) + parSize; stk_par := MAX(0, int - 6) + MAX(0, flt - 8) + ELSIF cconv IN {PROG.fastcall, PROG._fastcall} THEN + IF parSize = 0 THEN + callconv := IL.call_stack + ELSIF parSize = 1 THEN + callconv := IL.call_fast1 + ELSIF parSize >= 2 THEN + callconv := IL.call_fast2 + END; + fparSize := 0 ELSE callconv := IL.call_stack; fparSize := 0 diff --git a/source/UTILS.ob07 b/source/UTILS.ob07 index d87a32c..de0fd80 100644 --- a/source/UTILS.ob07 +++ b/source/UTILS.ob07 @@ -23,8 +23,8 @@ CONST max32* = 2147483647; vMajor* = 1; - vMinor* = 55; - Date* = "30-apr-2022"; + vMinor* = 56; + Date* = "21-jun-2022"; FILE_EXT* = ".ob07"; RTL_NAME* = "RTL"; diff --git a/source/X86.ob07 b/source/X86.ob07 index c9f409a..7212465 100644 --- a/source/X86.ob07 +++ b/source/X86.ob07 @@ -775,6 +775,14 @@ BEGIN drop; ASSERT(R.top = -1) + |IL.opFASTCALL: + IF param2 = 1 THEN + pop(ecx) + ELSIF param2 = 2 THEN + pop(ecx); + pop(edx) + END + |IL.opPRECALL: PushAll(0); IF (param2 # 0) & (fr >= 0) THEN @@ -832,6 +840,15 @@ BEGIN SetLabel(param1); + IF cmd.param3 > 0 THEN + pop(eax); + IF cmd.param3 >= 2 THEN + push(edx) + END; + push(ecx); + push(eax) + END; + push(ebp); mov(ebp, esp);