Merge pull request #151 from greg-king5/fastcall
Make __fastcall__ be the default calling convention.
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<article>
|
<article>
|
||||||
<title>cc65 Users Guide
|
<title>cc65 Users Guide
|
||||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
||||||
<date>2000-09-03, 2001-10-02, 2005-08-01
|
<date>2015-05-26
|
||||||
|
|
||||||
<abstract>
|
<abstract>
|
||||||
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
||||||
@@ -74,6 +74,7 @@ Short options:
|
|||||||
|
|
||||||
Long options:
|
Long options:
|
||||||
--add-source Include source as comment
|
--add-source Include source as comment
|
||||||
|
--all-cdecl Make functions default to __cdecl__
|
||||||
--bss-name seg Set the name of the BSS segment
|
--bss-name seg Set the name of the BSS segment
|
||||||
--check-stack Generate stack overflow checks
|
--check-stack Generate stack overflow checks
|
||||||
--code-name seg Set the name of the CODE segment
|
--code-name seg Set the name of the CODE segment
|
||||||
@@ -114,6 +115,14 @@ Here is a description of all the command line options:
|
|||||||
|
|
||||||
<descrip>
|
<descrip>
|
||||||
|
|
||||||
|
<tag><tt>--all-cdecl</tt></tag>
|
||||||
|
|
||||||
|
Tells the compiler that functions which aren't declared explicitly with
|
||||||
|
either the <tt/__cdecl__/ or <tt/__fastcall__/ calling conventions should
|
||||||
|
have the cdecl convention. (Normally, functions that aren't variadic are
|
||||||
|
fast-called.)
|
||||||
|
|
||||||
|
|
||||||
<label id="option-bss-name">
|
<label id="option-bss-name">
|
||||||
<tag><tt>--bss-name seg</tt></tag>
|
<tag><tt>--bss-name seg</tt></tag>
|
||||||
|
|
||||||
@@ -550,9 +559,10 @@ and the one defined by the ISO standard:
|
|||||||
be passed as parameters by value. However, struct assignment *is*
|
be passed as parameters by value. However, struct assignment *is*
|
||||||
possible.
|
possible.
|
||||||
<p>
|
<p>
|
||||||
<item> Part of the C library is available only with fastcall calling
|
<item> Most of the C library is available with only the fastcall calling
|
||||||
conventions (see below). It means that you must not mix pointers to
|
convention (<ref id="extension-fastcall" name="see below">). It means
|
||||||
those functions with pointers to user-written, not-fastcall functions.
|
that you must not mix pointers to those functions with pointers to
|
||||||
|
user-written, cdecl functions (the calling conventions are incompatible).
|
||||||
<p>
|
<p>
|
||||||
<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad
|
<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad
|
||||||
as it sounds, since the 6502 has so few registers that it isn't
|
as it sounds, since the 6502 has so few registers that it isn't
|
||||||
@@ -590,30 +600,58 @@ This cc65 version has some extensions to the ISO C standard.
|
|||||||
<ref id="inline-asm" name="see there">.
|
<ref id="inline-asm" name="see there">.
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<item> There is a special calling convention named "fastcall".
|
<label id="extension-fastcall">
|
||||||
The syntax for a function declaration using fastcall is
|
<item> The normal calling convention -- for non-variadic functions -- is
|
||||||
|
named "fastcall". The syntax for a function declaration that
|
||||||
|
<em/explicitly/ uses fastcall is
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
<return type> fastcall <function name> (<parameter list>)
|
<return type> fastcall <function name> (<parameter list>)
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
or
|
or
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
<return type> __fastcall__ <function name> (<parameter list>)
|
<return type> __fastcall__ <function name> (<parameter list>)
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
An example would be
|
An example is
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
void __fastcall__ f (unsigned char c)
|
void __fastcall__ f (unsigned char c)
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
The first form of the fastcall keyword is in the user namespace and can
|
The first form of the fastcall keyword is in the user namespace and can
|
||||||
therefore be disabled with the <tt><ref id="option--standard"
|
therefore be disabled with the <tt><ref id="option--standard"
|
||||||
name="--standard"></tt> command line option.
|
name="--standard"></tt> command line option.
|
||||||
|
|
||||||
For functions declared as <tt/fastcall/, the rightmost parameter is not
|
For functions that are <tt/fastcall/, the rightmost parameter is not
|
||||||
pushed on the stack but left in the primary register when the function
|
pushed on the stack but left in the primary register when the function
|
||||||
is called. This will reduce the cost when calling assembler functions
|
is called. That significantly reduces the cost of calling those functions.
|
||||||
significantly, especially when the function itself is rather small.
|
<newline><newline>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
<item> There is another calling convention named "cdecl". Variadic functions
|
||||||
|
(their prototypes have an ellipsis [<tt/.../]) always use that
|
||||||
|
convention. The syntax for a function declaration using cdecl is
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
<return type> cdecl <function name> (<parameter list>)
|
||||||
|
</verb></tscreen>
|
||||||
|
or
|
||||||
|
<tscreen><verb>
|
||||||
|
<return type> __cdecl__ <function name> (<parameter list>)
|
||||||
|
</verb></tscreen>
|
||||||
|
An example is
|
||||||
|
<tscreen><verb>
|
||||||
|
int* __cdecl__ f (unsigned char c)
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
The first form of the cdecl keyword is in the user namespace;
|
||||||
|
and therefore, can be disabled with the <tt/<ref id="option--standard"
|
||||||
|
name="--standard">/ command-line option.
|
||||||
|
|
||||||
|
For functions that are <tt/cdecl/, the rightmost parameter is pushed
|
||||||
|
onto the stack before the function is called. That increases the cost
|
||||||
|
of calling those functions, especially when they are called from many
|
||||||
|
places.<newline><newline>
|
||||||
|
<p>
|
||||||
|
|
||||||
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
|
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
|
||||||
Both refer to the primary register that is used by the compiler to
|
Both refer to the primary register that is used by the compiler to
|
||||||
evaluate expressions or return function results. <tt/__AX__/ is of
|
evaluate expressions or return function results. <tt/__AX__/ is of
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<article>
|
<article>
|
||||||
<title>Defining a Custom cc65 Target
|
<title>Defining a Custom cc65 Target
|
||||||
<author>Bruce Reidenbach
|
<author>Bruce Reidenbach
|
||||||
<date>2010-02-22
|
<date>2015-03-13
|
||||||
|
|
||||||
<abstract>
|
<abstract>
|
||||||
This section provides step-by-step instructions on how to use the cc65
|
This section provides step-by-step instructions on how to use the cc65
|
||||||
@@ -525,15 +525,16 @@ The first step in creating the assembly language code for the driver is
|
|||||||
to determine how to pass the C arguments to the assembly language
|
to determine how to pass the C arguments to the assembly language
|
||||||
routine. The cc65 toolset allows the user to specify whether the data
|
routine. The cc65 toolset allows the user to specify whether the data
|
||||||
is passed to a subroutine via the stack or by the processor registers by
|
is passed to a subroutine via the stack or by the processor registers by
|
||||||
using the <tt>__fastcall__</tt> function declaration (note that there
|
using the <tt/__fastcall__/ and <tt/__cdecl__/ function qualifiers (note that
|
||||||
are two underscore characters in front of and two behind the
|
there are two underscore characters in front of and two behind each
|
||||||
<tt>fastcall</tt> declaration). When <tt>__fastcall__</tt> is
|
qualifier). <tt/__fastcall__/ is the default. When <tt/__cdecl__/ <em/isn't/
|
||||||
specified, the rightmost argument in the function call is passed to the
|
specified, and the function isn't variadic (i.e., its prototype doesn't have
|
||||||
|
an ellipsis), the rightmost argument in the function call is passed to the
|
||||||
subroutine using the 6502 registers instead of the stack. Note that if
|
subroutine using the 6502 registers instead of the stack. Note that if
|
||||||
there is only one argument in the function call, the execution overhead
|
there is only one argument in the function call, the execution overhead
|
||||||
required by the stack interface routines is completely avoided.
|
required by the stack interface routines is completely avoided.
|
||||||
|
|
||||||
Without <tt>__fastcall__</tt>, the argument is loaded in the A and X
|
With <tt/__cdecl__</tt>, the last argument is loaded into the A and X
|
||||||
registers and then pushed onto the stack via a call to <tt>pushax</tt>.
|
registers and then pushed onto the stack via a call to <tt>pushax</tt>.
|
||||||
The first thing the subroutine does is retrieve the argument from the
|
The first thing the subroutine does is retrieve the argument from the
|
||||||
stack via a call to <tt>ldax0sp</tt>, which copies the values into the A
|
stack via a call to <tt>ldax0sp</tt>, which copies the values into the A
|
||||||
@@ -561,7 +562,7 @@ _foo: jsr ldax0sp ; Retrieve A and X from the stack
|
|||||||
jmp incsp2 ; Pop A and X from the stack (includes return)
|
jmp incsp2 ; Pop A and X from the stack (includes return)
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
If <tt>__fastcall__</tt> is specified, the argument is loaded into the A
|
If <tt/__cdecl__/ isn't specified, then the argument is loaded into the A
|
||||||
and X registers as before, but the subroutine is then called
|
and X registers as before, but the subroutine is then called
|
||||||
immediately. The subroutine does not need to retrieve the argument
|
immediately. The subroutine does not need to retrieve the argument
|
||||||
since the value is already available in the A and X registers.
|
since the value is already available in the A and X registers.
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
/* */
|
/* */
|
||||||
/* ace.h */
|
/* ace.h */
|
||||||
/* */
|
/* */
|
||||||
/* ACE system specific definitions */
|
/* ACE system-specific definitions */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2001 Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -61,9 +61,9 @@ struct aceDirentBuf {
|
|||||||
char ad_name [17]; /* Name itself, ASCIIZ */
|
char ad_name [17]; /* Name itself, ASCIIZ */
|
||||||
};
|
};
|
||||||
|
|
||||||
int aceDirOpen (char* dir);
|
int __cdecl__ aceDirOpen (char* dir);
|
||||||
int aceDirClose (int handle);
|
int __cdecl__ aceDirClose (int handle);
|
||||||
int aceDirRead (int handle, struct aceDirentBuf* buf);
|
int __cdecl__ aceDirRead (int handle, struct aceDirentBuf* buf);
|
||||||
|
|
||||||
/* Type of an ACE key. Key in low byte, shift mask in high byte */
|
/* Type of an ACE key. Key in low byte, shift mask in high byte */
|
||||||
typedef unsigned int aceKey;
|
typedef unsigned int aceKey;
|
||||||
@@ -92,23 +92,23 @@ typedef unsigned int aceKey;
|
|||||||
#define aceOP_RPTRATE 11 /* Key repeat rate */
|
#define aceOP_RPTRATE 11 /* Key repeat rate */
|
||||||
|
|
||||||
/* Console functions */
|
/* Console functions */
|
||||||
void aceConWrite (char* buf, size_t count);
|
void __cdecl__ aceConWrite (char* buf, size_t count);
|
||||||
void aceConPutLit (int c);
|
void __cdecl__ aceConPutLit (int c);
|
||||||
void aceConPos (unsigned x, unsigned y);
|
void __cdecl__ aceConPos (unsigned x, unsigned y);
|
||||||
void aceConGetPos (unsigned* x, unsigned* y);
|
void __cdecl__ aceConGetPos (unsigned* x, unsigned* y);
|
||||||
unsigned aceConGetX (void);
|
unsigned aceConGetX (void);
|
||||||
unsigned aceConGetY (void);
|
unsigned aceConGetY (void);
|
||||||
char* aceConInput (char* buf, unsigned initial);
|
char __cdecl__* aceConInput (char* buf, unsigned initial);
|
||||||
int aceConStopKey (void);
|
int aceConStopKey (void);
|
||||||
aceKey aceConGetKey (void);
|
aceKey aceConGetKey (void);
|
||||||
int aceConKeyAvail (aceKey* key);
|
int __cdecl__ aceConKeyAvail (aceKey* key);
|
||||||
void aceConKeyMat (char* matrix);
|
void __cdecl__ aceConKeyMat (char* matrix);
|
||||||
void aceConSetOpt (unsigned char opt, unsigned char val);
|
void __cdecl__ aceConSetOpt (unsigned char opt, unsigned char val);
|
||||||
int aceConGetOpt (unsigned char opt);
|
int __cdecl__ aceConGetOpt (unsigned char opt);
|
||||||
|
|
||||||
/* Misc stuff */
|
/* Misc stuff */
|
||||||
int aceMiscIoPeek (unsigned addr);
|
int __cdecl__ aceMiscIoPeek (unsigned addr);
|
||||||
void aceMiscIoPoke (unsigned addr, unsigned char val);
|
void __cdecl__ aceMiscIoPoke (unsigned addr, unsigned char val);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
# define assert(expr)
|
# define assert(expr)
|
||||||
#else
|
#else
|
||||||
extern void _afailed (const char*, unsigned);
|
extern void __fastcall__ _afailed (const char*, unsigned);
|
||||||
# define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__))
|
# define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -222,7 +222,7 @@ void cbm_k_unlsn (void);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int cbm_load (const char* name, unsigned char device, void* data);
|
unsigned int __fastcall__ cbm_load (const char* name, unsigned char device, void* data);
|
||||||
/* Loads file "name", from given device, to given address -- or, to the load
|
/* Loads file "name", from given device, to given address -- or, to the load
|
||||||
** address of the file if "data" is the null pointer (like load"name",8,1
|
** address of the file if "data" is the null pointer (like load"name",8,1
|
||||||
** in BASIC).
|
** in BASIC).
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
/* (C) 1998-2000, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -88,7 +88,7 @@ unsigned __fastcall__ DbgDisAsmLen (unsigned Addr);
|
|||||||
int __fastcall__ DbgIsRAM (unsigned Addr);
|
int __fastcall__ DbgIsRAM (unsigned Addr);
|
||||||
/* Return true if we can read and write the given address */
|
/* Return true if we can read and write the given address */
|
||||||
|
|
||||||
char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
|
char* __cdecl__ DbgMemDump (unsigned Addr, char* Buf, unsigned char Len);
|
||||||
/* Create a line of a memory dump in the given buffer. The buffer contains
|
/* Create a line of a memory dump in the given buffer. The buffer contains
|
||||||
** the starting address (4 digits hex), then Len bytes in this format:
|
** the starting address (4 digits hex), then Len bytes in this format:
|
||||||
** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes
|
** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* lynx.h */
|
/* lynx.h */
|
||||||
/* */
|
/* */
|
||||||
/* Lynx system specific definitions */
|
/* Lynx system-specific definitions */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
@@ -109,25 +109,25 @@ extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */
|
|||||||
/* Sound support */
|
/* Sound support */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void lynx_snd_init ();
|
void lynx_snd_init (void);
|
||||||
/* Initialize the sound driver */
|
/* Initialize the sound driver */
|
||||||
|
|
||||||
void lynx_snd_pause ();
|
void lynx_snd_pause (void);
|
||||||
/* Pause sound */
|
/* Pause sound */
|
||||||
|
|
||||||
void lynx_snd_continue ();
|
void lynx_snd_continue (void);
|
||||||
/* Continue sound after pause */
|
/* Continue sound after pause */
|
||||||
|
|
||||||
void __fastcall__ lynx_snd_play (unsigned char channel, unsigned char *music);
|
void __fastcall__ lynx_snd_play (unsigned char channel, unsigned char *music);
|
||||||
/* Play tune on channel */
|
/* Play tune on channel */
|
||||||
|
|
||||||
void lynx_snd_stop ();
|
void lynx_snd_stop (void);
|
||||||
/* Stop sound on all channels */
|
/* Stop sound on all channels */
|
||||||
|
|
||||||
void __fastcall__ lynx_snd_stop_channel (unsigned char channel);
|
void __fastcall__ lynx_snd_stop_channel (unsigned char channel);
|
||||||
/* Stop sound on all channels */
|
/* Stop sound on all channels */
|
||||||
|
|
||||||
unsigned char lynx_snd_active();
|
unsigned char lynx_snd_active(void);
|
||||||
/* Show which channels are active */
|
/* Show which channels are active */
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2001 Piotr Fusik <fox@scene.pl> */
|
/* (C) 2000-2015 Piotr Fusik <fox@scene.pl> */
|
||||||
/* */
|
/* */
|
||||||
/* This file is based on the zlib.h from 'zlib' general purpose compression */
|
/* This file is based on the zlib.h from 'zlib' general purpose compression */
|
||||||
/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */
|
/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */
|
||||||
@@ -83,8 +83,8 @@ unsigned __fastcall__ inflatemem (char* dest, const char* source);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int uncompress (char* dest, unsigned* destLen,
|
int __fastcall__ uncompress (char* dest, unsigned* destLen,
|
||||||
const char* source, unsigned sourceLen);
|
const char* source, unsigned sourceLen);
|
||||||
/*
|
/*
|
||||||
Original zlib description:
|
Original zlib description:
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
** Marc 'BlackJack' Rintsch, 06.03.2001
|
** Marc 'BlackJack' Rintsch, 06.03.2001
|
||||||
**
|
**
|
||||||
** unsigned int cbm_load(const char* name,
|
** unsigned int __fastcall__ cbm_load(const char* name,
|
||||||
** unsigned char device,
|
** unsigned char device,
|
||||||
** const unsigned char* data);
|
** const unsigned char* data);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cbm.h>
|
#include <cbm.h>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
/* loads file "name" from given device to given address or to the load address
|
/* loads file "name" from given device to given address or to the load address
|
||||||
** of the file if "data" is 0
|
** of the file if "data" is 0
|
||||||
*/
|
*/
|
||||||
unsigned int cbm_load(const char* name, unsigned char device, void* data)
|
unsigned int __fastcall__ cbm_load(const char* name, unsigned char device, void* data)
|
||||||
{
|
{
|
||||||
/* LFN is set to 0; but, it's not needed for loading
|
/* LFN is set to 0; but, it's not needed for loading
|
||||||
** (BASIC V2 sets it to the value of the SA for LOAD).
|
** (BASIC V2 sets it to the value of the SA for LOAD).
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
** _afailed.c
|
** _afailed.c
|
||||||
**
|
**
|
||||||
** Ullrich von Bassewitz, 06.06.1998
|
** 1998-06-06, Ullrich von Bassewitz
|
||||||
|
** 2015-03-13, Greg King
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _afailed (char* file, unsigned line)
|
void __fastcall__ _afailed (char* file, unsigned line)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line);
|
fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line);
|
||||||
exit (2);
|
exit (2);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
;
|
;
|
||||||
; Ullrich von Bassewitz, 11.08.1998
|
; Ullrich von Bassewitz, 11.08.1998
|
||||||
;
|
;
|
||||||
; char* DbgMemDump (unsigend Addr, char* Buf, unsigned char Length);
|
; char* __cdecl__ DbgMemDump (unsigend Addr, char* Buf, unsigned char Length);
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _DbgMemDump
|
.export _DbgMemDump
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
int uncompress (char* dest, unsigned* destLen,
|
int __fastcall__ uncompress (char* dest, unsigned* destLen,
|
||||||
const char* source, unsigned sourceLen)
|
const char* source, unsigned sourceLen)
|
||||||
{
|
{
|
||||||
unsigned len;
|
unsigned len;
|
||||||
unsigned char* ptr;
|
unsigned char* ptr;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2001-2012, Ullrich von Bassewitz */
|
/* (C) 2001-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "codeseg.h"
|
#include "codeseg.h"
|
||||||
#include "datatype.h"
|
#include "datatype.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "global.h"
|
||||||
#include "reginfo.h"
|
#include "reginfo.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "codeinfo.h"
|
#include "codeinfo.h"
|
||||||
@@ -386,33 +387,35 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
|
|||||||
** Search for it in the list of builtin functions.
|
** Search for it in the list of builtin functions.
|
||||||
*/
|
*/
|
||||||
if (Name[0] == '_') {
|
if (Name[0] == '_') {
|
||||||
|
|
||||||
/* Search in the symbol table, skip the leading underscore */
|
/* Search in the symbol table, skip the leading underscore */
|
||||||
SymEntry* E = FindGlobalSym (Name+1);
|
SymEntry* E = FindGlobalSym (Name+1);
|
||||||
|
|
||||||
/* Did we find it in the top level table? */
|
/* Did we find it in the top-level table? */
|
||||||
if (E && IsTypeFunc (E->Type)) {
|
if (E && IsTypeFunc (E->Type)) {
|
||||||
|
|
||||||
FuncDesc* D = E->V.F.Func;
|
FuncDesc* D = E->V.F.Func;
|
||||||
|
|
||||||
/* A function may use the A or A/X registers if it is a fastcall
|
/* A variadic function will use the Y register (the parameter list
|
||||||
** function. If it is not a fastcall function but a variadic one,
|
** size is passed there). A fastcall function will use the A or A/X
|
||||||
** it will use the Y register (the parameter size is passed here).
|
** registers. In all other cases, no registers are used. However,
|
||||||
** In all other cases, no registers are used. However, we assume
|
** we assume that any function will destroy all registers.
|
||||||
** that any function will destroy all registers.
|
|
||||||
*/
|
*/
|
||||||
if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
|
if ((D->Flags & FD_VARIADIC) != 0) {
|
||||||
/* Will use registers depending on the last param */
|
|
||||||
unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
|
|
||||||
if (LastParamSize == 1) {
|
|
||||||
*Use = REG_A;
|
|
||||||
} else if (LastParamSize == 2) {
|
|
||||||
*Use = REG_AX;
|
|
||||||
} else {
|
|
||||||
*Use = REG_EAX;
|
|
||||||
}
|
|
||||||
} else if ((D->Flags & FD_VARIADIC) != 0) {
|
|
||||||
*Use = REG_Y;
|
*Use = REG_Y;
|
||||||
|
} else if (D->ParamCount > 0 &&
|
||||||
|
(AutoCDecl ?
|
||||||
|
IsQualFastcall (E->Type) :
|
||||||
|
!IsQualCDecl (E->Type))) {
|
||||||
|
/* Will use registers depending on the last param. */
|
||||||
|
switch (CheckedSizeOf (D->LastParam->Type)) {
|
||||||
|
case 1u:
|
||||||
|
*Use = REG_A;
|
||||||
|
break;
|
||||||
|
case 2u:
|
||||||
|
*Use = REG_AX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*Use = REG_EAX;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Will not use any registers */
|
/* Will not use any registers */
|
||||||
*Use = REG_NONE;
|
*Use = REG_NONE;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -293,15 +293,15 @@ void PrintType (FILE* F, const Type* T)
|
|||||||
/* Recursive call */
|
/* Recursive call */
|
||||||
PrintType (F, T + 1);
|
PrintType (F, T + 1);
|
||||||
if (T->A.L == UNSPECIFIED) {
|
if (T->A.L == UNSPECIFIED) {
|
||||||
fprintf (F, "[]");
|
fprintf (F, " []");
|
||||||
} else {
|
} else {
|
||||||
fprintf (F, "[%ld]", T->A.L);
|
fprintf (F, " [%ld]", T->A.L);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case T_TYPE_PTR:
|
case T_TYPE_PTR:
|
||||||
/* Recursive call */
|
/* Recursive call */
|
||||||
PrintType (F, T + 1);
|
PrintType (F, T + 1);
|
||||||
fprintf (F, "*");
|
fprintf (F, " *");
|
||||||
return;
|
return;
|
||||||
case T_TYPE_FUNC:
|
case T_TYPE_FUNC:
|
||||||
fprintf (F, "function returning ");
|
fprintf (F, "function returning ");
|
||||||
@@ -659,7 +659,7 @@ Type* GetBaseElementType (Type* T)
|
|||||||
** will return. Otherwise it will return the base element type, which means
|
** will return. Otherwise it will return the base element type, which means
|
||||||
** the element type that is not an array.
|
** the element type that is not an array.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
while (IsTypeArray (T)) {
|
while (IsTypeArray (T)) {
|
||||||
++T;
|
++T;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -603,6 +603,16 @@ INLINE int IsQualCDecl (const Type* T)
|
|||||||
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
|
# define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE int IsQualCConv (const Type* T)
|
||||||
|
/* Return true if the given type has a calling convention qualifier */
|
||||||
|
{
|
||||||
|
return (T->C & T_QUAL_CCONV) != 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
int IsVariadicFunc (const Type* T) attribute ((const));
|
int IsVariadicFunc (const Type* T) attribute ((const));
|
||||||
/* Return true if this is a function type or pointer to function type with
|
/* Return true if this is a function type or pointer to function type with
|
||||||
** variable parameter list
|
** variable parameter list
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2013, Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -85,7 +85,7 @@ struct StructInitData {
|
|||||||
|
|
||||||
|
|
||||||
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
|
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
|
||||||
/* Parse a type specificier */
|
/* Parse a type specifier */
|
||||||
|
|
||||||
static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
|
static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
|
||||||
/* Parse initialization of variables. Return the number of data bytes. */
|
/* Parse initialization of variables. Return the number of data bytes. */
|
||||||
@@ -335,18 +335,30 @@ static void FixQualifiers (Type* DataType)
|
|||||||
T = DataType;
|
T = DataType;
|
||||||
while (T->C != T_END) {
|
while (T->C != T_END) {
|
||||||
if (IsTypePtr (T)) {
|
if (IsTypePtr (T)) {
|
||||||
|
/* Calling convention qualifier on the pointer? */
|
||||||
|
if (IsQualCConv (T)) {
|
||||||
|
/* Pull the convention off of the pointer */
|
||||||
|
Q = T[0].C & T_QUAL_CCONV;
|
||||||
|
T[0].C &= ~T_QUAL_CCONV;
|
||||||
|
|
||||||
/* Fastcall qualifier on the pointer? */
|
/* Pointer to a function which doesn't have an explicit convention? */
|
||||||
if (IsQualFastcall (T)) {
|
if (IsTypeFunc (T + 1)) {
|
||||||
/* Pointer to function which is not fastcall? */
|
if (IsQualCConv (T + 1)) {
|
||||||
if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
|
if ((T[1].C & T_QUAL_CCONV) == Q) {
|
||||||
/* Move the fastcall qualifier from the pointer to
|
Warning ("Pointer duplicates function's calling convention");
|
||||||
** the function.
|
} else {
|
||||||
*/
|
Error ("Function's and pointer's calling conventions are different");
|
||||||
T[0].C &= ~T_QUAL_FASTCALL;
|
}
|
||||||
T[1].C |= T_QUAL_FASTCALL;
|
} else {
|
||||||
|
if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) {
|
||||||
|
Error ("Variadic-function pointers cannot be __fastcall__");
|
||||||
|
} else {
|
||||||
|
/* Move the qualifier from the pointer to the function. */
|
||||||
|
T[1].C |= Q;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Error ("Invalid `_fastcall__' qualifier for pointer");
|
Error ("Not pointer to a function; can't use a calling convention");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,8 +367,8 @@ static void FixQualifiers (Type* DataType)
|
|||||||
if (Q == T_QUAL_NONE) {
|
if (Q == T_QUAL_NONE) {
|
||||||
/* No address size qualifiers specified */
|
/* No address size qualifiers specified */
|
||||||
if (IsTypeFunc (T+1)) {
|
if (IsTypeFunc (T+1)) {
|
||||||
/* Pointer to function. Use the qualifier from the function
|
/* Pointer to function. Use the qualifier from the function,
|
||||||
** or the default if the function don't has one.
|
** or the default if the function doesn't have one.
|
||||||
*/
|
*/
|
||||||
Q = (T[1].C & T_QUAL_ADDRSIZE);
|
Q = (T[1].C & T_QUAL_ADDRSIZE);
|
||||||
if (Q == T_QUAL_NONE) {
|
if (Q == T_QUAL_NONE) {
|
||||||
@@ -368,7 +380,7 @@ static void FixQualifiers (Type* DataType)
|
|||||||
T[0].C |= Q;
|
T[0].C |= Q;
|
||||||
} else {
|
} else {
|
||||||
/* We have address size qualifiers. If followed by a function,
|
/* We have address size qualifiers. If followed by a function,
|
||||||
** apply these also to the function.
|
** apply them to the function also.
|
||||||
*/
|
*/
|
||||||
if (IsTypeFunc (T+1)) {
|
if (IsTypeFunc (T+1)) {
|
||||||
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
|
TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
|
||||||
@@ -489,7 +501,7 @@ static void ParseEnumDecl (void)
|
|||||||
|
|
||||||
|
|
||||||
static int ParseFieldWidth (Declaration* Decl)
|
static int ParseFieldWidth (Declaration* Decl)
|
||||||
/* Parse an optional field width. Returns -1 if no field width is speficied,
|
/* Parse an optional field width. Returns -1 if no field width is specified,
|
||||||
** otherwise the width of the field.
|
** otherwise the width of the field.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
@@ -862,7 +874,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
|
|||||||
|
|
||||||
|
|
||||||
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
||||||
/* Parse a type specificier */
|
/* Parse a type specifier */
|
||||||
{
|
{
|
||||||
ident Ident;
|
ident Ident;
|
||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
@@ -1376,13 +1388,13 @@ static FuncDesc* ParseFuncDecl (void)
|
|||||||
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
||||||
/* Recursively process declarators. Build a type array in reverse order. */
|
/* Recursively process declarators. Build a type array in reverse order. */
|
||||||
{
|
{
|
||||||
/* Read optional function or pointer qualifiers. These modify the
|
/* Read optional function or pointer qualifiers. They modify the
|
||||||
** identifier or token to the right. For convenience, we allow the fastcall
|
** identifier or token to the right. For convenience, we allow a calling
|
||||||
** qualifier also for pointers here. If it is a pointer-to-function, the
|
** convention also for pointers here. If it's a pointer-to-function, the
|
||||||
** qualifier will later be transfered to the function itself. If it's a
|
** qualifier later will be transfered to the function itself. If it's a
|
||||||
** pointer to something else, it will be flagged as an error.
|
** pointer to something else, it will be flagged as an error.
|
||||||
*/
|
*/
|
||||||
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
|
TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV);
|
||||||
|
|
||||||
/* Pointer to something */
|
/* Pointer to something */
|
||||||
if (CurTok.Tok == TOK_STAR) {
|
if (CurTok.Tok == TOK_STAR) {
|
||||||
@@ -1390,10 +1402,10 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
|||||||
/* Skip the star */
|
/* Skip the star */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Allow const, restrict and volatile qualifiers */
|
/* Allow const, restrict, and volatile qualifiers */
|
||||||
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
|
Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT);
|
||||||
|
|
||||||
/* Parse the type, the pointer points to */
|
/* Parse the type that the pointer points to */
|
||||||
Declarator (Spec, D, Mode);
|
Declarator (Spec, D, Mode);
|
||||||
|
|
||||||
/* Add the type */
|
/* Add the type */
|
||||||
@@ -1443,7 +1455,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
|||||||
|
|
||||||
/* We cannot specify fastcall for variadic functions */
|
/* We cannot specify fastcall for variadic functions */
|
||||||
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
||||||
Error ("Variadic functions cannot be `__fastcall__'");
|
Error ("Variadic functions cannot be __fastcall__");
|
||||||
Qualifiers &= ~T_QUAL_FASTCALL;
|
Qualifiers &= ~T_QUAL_FASTCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* expr.c
|
/* expr.c
|
||||||
**
|
**
|
||||||
** Ullrich von Bassewitz, 21.06.1998
|
** 1998-06-21, Ullrich von Bassewitz
|
||||||
|
** 2015-04-19, Greg King
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -470,9 +471,11 @@ static void FunctionCall (ExprDesc* Expr)
|
|||||||
/* Handle function pointers transparently */
|
/* Handle function pointers transparently */
|
||||||
IsFuncPtr = IsTypeFuncPtr (Expr->Type);
|
IsFuncPtr = IsTypeFuncPtr (Expr->Type);
|
||||||
if (IsFuncPtr) {
|
if (IsFuncPtr) {
|
||||||
|
/* Check whether it's a fastcall function that has parameters */
|
||||||
/* Check wether it's a fastcall function that has parameters */
|
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 &&
|
||||||
IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
|
(AutoCDecl ?
|
||||||
|
IsQualFastcall (Expr->Type + 1) :
|
||||||
|
!IsQualCDecl (Expr->Type + 1));
|
||||||
|
|
||||||
/* Things may be difficult, depending on where the function pointer
|
/* Things may be difficult, depending on where the function pointer
|
||||||
** resides. If the function pointer is an expression of some sort
|
** resides. If the function pointer is an expression of some sort
|
||||||
@@ -517,7 +520,10 @@ static void FunctionCall (ExprDesc* Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't inline the function, get fastcall info */
|
/* If we didn't inline the function, get fastcall info */
|
||||||
IsFastcall = IsQualFastcall (Expr->Type);
|
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 &&
|
||||||
|
(AutoCDecl ?
|
||||||
|
IsQualFastcall (Expr->Type) :
|
||||||
|
!IsQualCDecl (Expr->Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the parameter list */
|
/* Parse the parameter list */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2012, Ullrich von Bassewitz */
|
/* (C) 2000-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -460,6 +460,9 @@ void NewFunc (SymEntry* Func)
|
|||||||
*/
|
*/
|
||||||
if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) {
|
if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) {
|
||||||
g_importmainargs ();
|
g_importmainargs ();
|
||||||
|
|
||||||
|
/* The start-up code doesn't fast-call main(). */
|
||||||
|
Func->Type->C |= T_QUAL_CDECL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if this is a main function in a C99 environment that
|
/* Determine if this is a main function in a C99 environment that
|
||||||
@@ -478,13 +481,12 @@ void NewFunc (SymEntry* Func)
|
|||||||
PushLiteralPool (Func);
|
PushLiteralPool (Func);
|
||||||
|
|
||||||
/* If this is a fastcall function, push the last parameter onto the stack */
|
/* If this is a fastcall function, push the last parameter onto the stack */
|
||||||
if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
|
if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 &&
|
||||||
|
(AutoCDecl ?
|
||||||
|
IsQualFastcall (Func->Type) :
|
||||||
|
!IsQualCDecl (Func->Type))) {
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
|
|
||||||
/* Fastcall functions may never have an ellipsis or the compiler is buggy */
|
|
||||||
CHECK ((D->Flags & FD_VARIADIC) == 0);
|
|
||||||
|
|
||||||
/* Generate the push */
|
/* Generate the push */
|
||||||
if (IsTypeFunc (D->LastParam->Type)) {
|
if (IsTypeFunc (D->LastParam->Type)) {
|
||||||
/* Pointer to function */
|
/* Pointer to function */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
|
|
||||||
unsigned char AddSource = 0; /* Add source lines as comments */
|
unsigned char AddSource = 0; /* Add source lines as comments */
|
||||||
|
unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */
|
||||||
unsigned char DebugInfo = 0; /* Add debug info to the obj */
|
unsigned char DebugInfo = 0; /* Add debug info to the obj */
|
||||||
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
|
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
|
||||||
unsigned char DebugOptOutput = 0; /* Output debug stuff */
|
unsigned char DebugOptOutput = 0; /* Output debug stuff */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2012, Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
|
|
||||||
/* Options */
|
/* Options */
|
||||||
extern unsigned char AddSource; /* Add source lines as comments */
|
extern unsigned char AddSource; /* Add source lines as comments */
|
||||||
|
extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */
|
||||||
extern unsigned char DebugInfo; /* Add debug info to the obj */
|
extern unsigned char DebugInfo; /* Add debug info to the obj */
|
||||||
extern unsigned char PreprocessOnly; /* Just preprocess the input */
|
extern unsigned char PreprocessOnly; /* Just preprocess the input */
|
||||||
extern unsigned char DebugOptOutput; /* Output debug stuff */
|
extern unsigned char DebugOptOutput; /* Output debug stuff */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2013, Ullrich von Bassewitz */
|
/* (C) 2000-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -104,6 +104,7 @@ static void Usage (void)
|
|||||||
"\n"
|
"\n"
|
||||||
"Long options:\n"
|
"Long options:\n"
|
||||||
" --add-source\t\t\tInclude source as comment\n"
|
" --add-source\t\t\tInclude source as comment\n"
|
||||||
|
" --all-cdecl\t\t\tMake functions default to __cdecl__\n"
|
||||||
" --bss-name seg\t\tSet the name of the BSS segment\n"
|
" --bss-name seg\t\tSet the name of the BSS segment\n"
|
||||||
" --check-stack\t\t\tGenerate stack overflow checks\n"
|
" --check-stack\t\t\tGenerate stack overflow checks\n"
|
||||||
" --code-name seg\t\tSet the name of the CODE segment\n"
|
" --code-name seg\t\tSet the name of the CODE segment\n"
|
||||||
@@ -350,6 +351,15 @@ static void OptAddSource (const char* Opt attribute ((unused)),
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void OptAllCDecl (const char* Opt attribute ((unused)),
|
||||||
|
const char* Arg attribute ((unused)))
|
||||||
|
/* Make functions default to cdecl instead of fastcall. */
|
||||||
|
{
|
||||||
|
AutoCDecl = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
|
static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
|
||||||
/* Handle the --bss-name option */
|
/* Handle the --bss-name option */
|
||||||
{
|
{
|
||||||
@@ -790,6 +800,7 @@ int main (int argc, char* argv[])
|
|||||||
/* Program long options */
|
/* Program long options */
|
||||||
static const LongOpt OptTab[] = {
|
static const LongOpt OptTab[] = {
|
||||||
{ "--add-source", 0, OptAddSource },
|
{ "--add-source", 0, OptAddSource },
|
||||||
|
{ "--all-cdecl", 0, OptAllCDecl },
|
||||||
{ "--bss-name", 1, OptBssName },
|
{ "--bss-name", 1, OptBssName },
|
||||||
{ "--check-stack", 0, OptCheckStack },
|
{ "--check-stack", 0, OptCheckStack },
|
||||||
{ "--code-name", 1, OptCodeName },
|
{ "--code-name", 1, OptCodeName },
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
/* (C) 1998-2015, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "funcdesc.h"
|
#include "funcdesc.h"
|
||||||
|
#include "global.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "typecmp.h"
|
#include "typecmp.h"
|
||||||
|
|
||||||
@@ -245,23 +246,36 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LeftType == T_TYPE_FUNC) {
|
||||||
|
/* If a calling convention wasn't set explicitly,
|
||||||
|
** then assume the default one.
|
||||||
|
*/
|
||||||
|
if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) {
|
||||||
|
LeftQual |= (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
|
||||||
|
}
|
||||||
|
if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) {
|
||||||
|
RightQual |= (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (LeftQual != RightQual) {
|
if (LeftQual != RightQual) {
|
||||||
/* On the first indirection level, different qualifiers mean
|
/* On the first indirection level, different qualifiers mean
|
||||||
** that the types are still compatible. On the second level,
|
** that the types still are compatible. On the second level,
|
||||||
** this is a (maybe minor) error, so we create a special
|
** that is a (maybe minor) error. We create a special return-code
|
||||||
** return code, since a qualifier is dropped from a pointer.
|
** if a qualifier is dropped from a pointer. But, different calling
|
||||||
** Starting from the next level, the types are incompatible
|
** conventions are incompatible. Starting from the next level,
|
||||||
** if the qualifiers differ.
|
** the types are incompatible if the qualifiers differ.
|
||||||
*/
|
*/
|
||||||
|
/* (Debugging statement) */
|
||||||
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
|
/* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
|
||||||
switch (Indirections) {
|
switch (Indirections) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
/* A non const value on the right is compatible to a
|
/* A non-const value on the right is compatible to a
|
||||||
** const one to the left, same for volatile.
|
** const one to the left, same for volatile.
|
||||||
*/
|
*/
|
||||||
if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
|
if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
|
||||||
@@ -270,7 +284,11 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
} else {
|
} else {
|
||||||
SetResult (Result, TC_STRICT_COMPATIBLE);
|
SetResult (Result, TC_STRICT_COMPATIBLE);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* else fall through */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SetResult (Result, TC_INCOMPATIBLE);
|
SetResult (Result, TC_INCOMPATIBLE);
|
||||||
@@ -280,7 +298,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
|
|
||||||
/* Check for special type elements */
|
/* Check for special type elements */
|
||||||
switch (LeftType) {
|
switch (LeftType) {
|
||||||
|
|
||||||
case T_TYPE_PTR:
|
case T_TYPE_PTR:
|
||||||
++Indirections;
|
++Indirections;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ mymain(int argc,char **argv)
|
|||||||
} else {
|
} else {
|
||||||
/* why not using a function pointer ? */
|
/* why not using a function pointer ? */
|
||||||
f = &fact;
|
f = &fact;
|
||||||
print_num((*(long (*)())f)(n), base);
|
print_num((*(long (*)(int))f)(n), base);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -26,6 +26,13 @@ TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=
|
|||||||
|
|
||||||
all: $(TESTS)
|
all: $(TESTS)
|
||||||
|
|
||||||
|
# cq71.c and cq84.c have "K & R"-style syntax. And, some local forward
|
||||||
|
# function-declarations don't match the later global function definitions.
|
||||||
|
# Those programs fail when fastcall is used; but, the cdecl calling convention
|
||||||
|
# tolerates those conflicts. Therefore, make their functions default to cdecl.
|
||||||
|
#
|
||||||
|
$(WORKDIR)/cq71%prg $(WORKDIR)/cq84%prg: CC65FLAGS += -Wc --all-cdecl
|
||||||
|
|
||||||
$(WORKDIR)/%.prg: %.c
|
$(WORKDIR)/%.prg: %.c
|
||||||
$(CL65) $(CC65FLAGS) $< -o $@
|
$(CL65) $(CC65FLAGS) $< -o $@
|
||||||
$(SIM65) $(SIM65FLAGS) $@
|
$(SIM65) $(SIM65FLAGS) $@
|
||||||
|
|||||||
Reference in New Issue
Block a user