Added a command-line option to compile a program, with __cdecl__ as the default calling convention.

This commit is contained in:
Greg King
2015-04-22 09:59:23 -04:00
parent 2842b68a04
commit 8743e9911d
7 changed files with 56 additions and 18 deletions

View File

@@ -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>2015-03-14 <date>2015-04-21
<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,8 +559,9 @@ and the one defined by the ISO standard:
possible. possible.
<p> <p>
<item> Most of the C library is available only with the fastcall calling <item> Most of the C library is available only with the fastcall calling
convention (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, cdecl functions. that you must not mix pointers to those functions with pointers to
user-written, cdecl functions.
<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
@@ -589,6 +599,7 @@ 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>
<label id="extension-fastcall">
<item> The normal calling convention -- for non-variadic functions -- is <item> The normal calling convention -- for non-variadic functions -- is
named "fastcall". The syntax for a function declaration that named "fastcall". The syntax for a function declaration that
<em/explicitly/ uses fastcall is <em/explicitly/ uses fastcall is
@@ -611,10 +622,11 @@ This cc65 version has some extensions to the ISO C standard.
For functions that are <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. That significantly reduces the cost of calling functions. is called. That significantly reduces the cost of calling functions.
<newline><newline>
<p> <p>
<item> There is another calling convention named "cdecl". Variadic functions <item> There is another calling convention named "cdecl". Variadic functions
(their prototypes have an ellipsis &lsqb;<tt/.../&rsqb;) always use this (their prototypes have an ellipsis &lsqb;<tt/.../&rsqb;) always use that
convention. The syntax for a function declaration using cdecl is convention. The syntax for a function declaration using cdecl is
<tscreen><verb> <tscreen><verb>
@@ -626,16 +638,17 @@ This cc65 version has some extensions to the ISO C standard.
</verb></tscreen> </verb></tscreen>
An example would be An example would be
<tscreen><verb> <tscreen><verb>
void __cdecl__ f (unsigned char c) int * __cdecl__ f (unsigned char c)
</verb></tscreen> </verb></tscreen>
The first form of the cdecl keyword is in the user namespace and can
therefore be disabled with the <tt><ref id="option--standard" The first form of the cdecl keyword is in the user namespace;
name="--standard"></tt> command line option. and therefore, can be disabled with the <tt><ref id="option--standard"
name="--standard"></tt> command-line option.
For functions that are <tt/cdecl/, the rightmost parameter is pushed For functions that are <tt/cdecl/, the rightmost parameter is pushed
onto the stack before the function is called. That increases the cost onto the stack before the function is called. That increases the cost
of calling those functions, especially when they are called from many of calling those functions, especially when they are called from many
places. places.<newline><newline>
<p> <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__/.

View File

@@ -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"
@@ -400,7 +401,10 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
*/ */
if ((D->Flags & FD_VARIADIC) != 0) { if ((D->Flags & FD_VARIADIC) != 0) {
*Use = REG_Y; *Use = REG_Y;
} else if (!IsQualCDecl (E->Type) && D->ParamCount > 0) { } else if (D->ParamCount > 0 &&
(AutoCDecl ?
IsQualFastcall (E->Type) :
!IsQualCDecl (E->Type))) {
/* Will use registers depending on the last param. */ /* Will use registers depending on the last param. */
switch (CheckedSizeOf (D->LastParam->Type)) { switch (CheckedSizeOf (D->LastParam->Type)) {
case 1u: case 1u:

View File

@@ -1,7 +1,7 @@
/* expr.c /* expr.c
** **
** 1998-06-21, Ullrich von Bassewitz ** 1998-06-21, Ullrich von Bassewitz
** 2015-03-10, Greg King ** 2015-04-19, Greg King
*/ */
@@ -471,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 whether it's a fastcall function that has parameters */
IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && !IsQualCDecl (Expr->Type + 1) && (Func->ParamCount > 0); IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && 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
@@ -518,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 = (Func->Flags & FD_VARIADIC) == 0 && !IsQualCDecl (Expr->Type); IsFastcall = (Func->Flags & FD_VARIADIC) == 0 &&
(AutoCDecl ?
IsQualFastcall (Expr->Type) :
!IsQualCDecl (Expr->Type));
} }
/* Parse the parameter list */ /* Parse the parameter list */

View File

@@ -481,7 +481,10 @@ 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 ((D->Flags & FD_VARIADIC) == 0 && !IsQualCDecl (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;
/* Generate the push */ /* Generate the push */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 },