mirror of
https://github.com/cc65/cc65.git
synced 2024-11-18 00:07:21 +00:00
Merge pull request #2297 from acqn/WrappedCall
[cc65] Fixed wrapped call when the function was defined before its later declaration gets wrapped with the pragma
This commit is contained in:
commit
bc97bce8c1
@ -1613,13 +1613,13 @@ parameter with the <tt/#pragma/.
|
||||
|
||||
This pragma sets a wrapper for functions, often used for trampolines.
|
||||
|
||||
The name is a function returning <tt/void/, and taking no parameters.
|
||||
The <tt/name/ is a wrapper function returning <tt/void/, and taking no parameters.
|
||||
It must preserve the CPU's <tt/A/ and <tt/X/ registers if it wraps any
|
||||
<tt/__fastcall__/ functions that have parameters. It must preserve
|
||||
the <tt/Y/ register if it wraps any variadic functions (they have "<tt/.../"
|
||||
in their prototypes).
|
||||
|
||||
The identifier is an 8-bit number that's set into <tt/tmp4/. If the identifier
|
||||
The <tt/identifier/ is an 8-bit number that's set into <tt/tmp4/. If the <tt/identifier/
|
||||
is "bank", then ca65's <tt><url url="ca65.html#.BANK" name=".bank"></tt> function will be used
|
||||
to determine the number from the bank attribute defined in the linker config,
|
||||
see <url url="ld65.html#MEMORY" name="Other MEMORY area attributes">. Note that
|
||||
@ -1629,6 +1629,11 @@ parameter with the <tt/#pragma/.
|
||||
The address of a wrapped function is passed in <tt/ptr4/. The wrapper can
|
||||
call that function by using "<tt/jsr callptr4/".
|
||||
|
||||
All functions ever declared or defined when this pragma is in effect will be wrapped
|
||||
when they are called explicitly by their names later in the same translation unit.
|
||||
Invocation of these functions in any other ways, for example, that via a function
|
||||
pointer or in inline assembly code, will not be wrapped.
|
||||
|
||||
This feature is useful, for example, with banked memory, to switch banks
|
||||
automatically to where a wrapped function resides, and then to restore the
|
||||
previous bank when it returns.
|
||||
|
@ -61,7 +61,6 @@
|
||||
#include "standard.h"
|
||||
#include "staticassert.h"
|
||||
#include "symtab.h"
|
||||
#include "wrappedcall.h"
|
||||
#include "typeconv.h"
|
||||
|
||||
|
||||
@ -1965,9 +1964,6 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||
static FuncDesc* ParseFuncDecl (void)
|
||||
/* Parse the argument list of a function with the enclosing parentheses */
|
||||
{
|
||||
SymEntry* WrappedCall;
|
||||
unsigned int WrappedCallData;
|
||||
|
||||
/* Create a new function descriptor */
|
||||
FuncDesc* F = NewFuncDesc ();
|
||||
|
||||
@ -2023,13 +2019,6 @@ static FuncDesc* ParseFuncDecl (void)
|
||||
/* Leave the lexical level remembering the symbol tables */
|
||||
RememberFunctionLevel (F);
|
||||
|
||||
/* Did we have a WrappedCall for this function? */
|
||||
GetWrappedCall((void **) &WrappedCall, &WrappedCallData);
|
||||
if (WrappedCall) {
|
||||
F->WrappedCall = WrappedCall;
|
||||
F->WrappedCallData = WrappedCallData;
|
||||
}
|
||||
|
||||
/* Return the function descriptor */
|
||||
return F;
|
||||
}
|
||||
@ -2102,7 +2091,6 @@ static void DirectDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
|
||||
|
||||
/* Function declarator */
|
||||
FuncDesc* F;
|
||||
SymEntry* PrevEntry;
|
||||
|
||||
/* Parse the function declarator */
|
||||
F = ParseFuncDecl ();
|
||||
@ -2113,16 +2101,6 @@ static void DirectDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
|
||||
Qualifiers &= ~T_QUAL_FASTCALL;
|
||||
}
|
||||
|
||||
/* Was there a previous entry? If so, copy WrappedCall info from it */
|
||||
PrevEntry = FindGlobalSym (D->Ident);
|
||||
if (PrevEntry && PrevEntry->Flags & SC_FUNC) {
|
||||
FuncDesc* D = GetFuncDesc (PrevEntry->Type);
|
||||
if (D->WrappedCall && !F->WrappedCall) {
|
||||
F->WrappedCall = D->WrappedCall;
|
||||
F->WrappedCallData = D->WrappedCallData;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the function type. Be sure to bounds check the type buffer */
|
||||
NeedTypeSpace (D, 1);
|
||||
D->Type[D->Index].C = T_FUNC | Qualifiers;
|
||||
|
@ -1057,11 +1057,6 @@ static void FunctionCall (ExprDesc* Expr)
|
||||
|
||||
/* Special handling for function pointers */
|
||||
if (IsFuncPtr) {
|
||||
|
||||
if (Func->WrappedCall) {
|
||||
Warning ("Calling a wrapped function via a pointer, wrapped-call will not be used");
|
||||
}
|
||||
|
||||
/* If the function is not a fastcall function, load the pointer to
|
||||
** the function into the primary.
|
||||
*/
|
||||
@ -1110,18 +1105,18 @@ static void FunctionCall (ExprDesc* Expr)
|
||||
} else {
|
||||
|
||||
/* Normal function */
|
||||
if (Func->WrappedCall) {
|
||||
if (Expr->Sym && Expr->Sym->V.F.WrappedCall) {
|
||||
char tmp[64];
|
||||
StrBuf S = AUTO_STRBUF_INITIALIZER;
|
||||
|
||||
if (Func->WrappedCallData == WRAPPED_CALL_USE_BANK) {
|
||||
if (Expr->Sym->V.F.WrappedCallData == WRAPPED_CALL_USE_BANK) {
|
||||
/* Store the bank attribute in tmp4 */
|
||||
SB_AppendStr (&S, "ldy #<.bank(_");
|
||||
SB_AppendStr (&S, (const char*) Expr->Name);
|
||||
SB_AppendChar (&S, ')');
|
||||
} else {
|
||||
/* Store the WrappedCall data in tmp4 */
|
||||
sprintf(tmp, "ldy #%u", Func->WrappedCallData);
|
||||
sprintf(tmp, "ldy #%u", Expr->Sym->V.F.WrappedCallData);
|
||||
SB_AppendStr (&S, tmp);
|
||||
}
|
||||
g_asmcode (&S);
|
||||
@ -1154,7 +1149,7 @@ static void FunctionCall (ExprDesc* Expr)
|
||||
|
||||
SB_Done (&S);
|
||||
|
||||
g_call (CG_CallFlags (Expr->Type), Func->WrappedCall->Name, ArgSize);
|
||||
g_call (CG_CallFlags (Expr->Type), Expr->Sym->V.F.WrappedCall->Name, ArgSize);
|
||||
} else {
|
||||
g_call (CG_CallFlags (Expr->Type), (const char*) Expr->Name, ArgSize);
|
||||
}
|
||||
@ -1328,6 +1323,7 @@ static void Primary (ExprDesc* E)
|
||||
E->Type = type_int;
|
||||
}
|
||||
|
||||
E->Sym = Sym;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -61,8 +61,6 @@ FuncDesc* NewFuncDesc (void)
|
||||
F->ParamSize = 0;
|
||||
F->LastParam = 0;
|
||||
F->FuncDef = 0;
|
||||
F->WrappedCall = 0;
|
||||
F->WrappedCallData = 0;
|
||||
|
||||
/* Return the new struct */
|
||||
return F;
|
||||
|
@ -70,8 +70,6 @@ struct FuncDesc {
|
||||
unsigned ParamSize; /* Size of the parameters */
|
||||
struct SymEntry* LastParam; /* Pointer to last parameter */
|
||||
struct FuncDesc* FuncDef; /* Descriptor used in definition */
|
||||
struct SymEntry* WrappedCall; /* Pointer to the WrappedCall */
|
||||
unsigned int WrappedCallData; /* The WrappedCall's user data */
|
||||
};
|
||||
|
||||
|
||||
|
@ -159,6 +159,8 @@ struct SymEntry {
|
||||
struct {
|
||||
struct SegContext* Seg; /* SegContext for this function */
|
||||
struct LiteralPool* LitPool; /* Literal pool for this function */
|
||||
struct SymEntry* WrappedCall; /* Pointer to the WrappedCall */
|
||||
unsigned int WrappedCallData; /* The WrappedCall's user data */
|
||||
} F;
|
||||
|
||||
/* Label name for static symbols */
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "symentry.h"
|
||||
#include "typecmp.h"
|
||||
#include "typeconv.h"
|
||||
#include "wrappedcall.h"
|
||||
#include "symtab.h"
|
||||
|
||||
|
||||
@ -1407,24 +1408,30 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
||||
}
|
||||
|
||||
if (Entry == 0) {
|
||||
|
||||
/* Create a new entry */
|
||||
Entry = NewSymEntry (Name, Flags);
|
||||
|
||||
/* Set the symbol attributes */
|
||||
Entry->Type = TypeDup (T);
|
||||
|
||||
/* If this is a function, clear additional fields */
|
||||
if (IsTypeFunc (T)) {
|
||||
Entry->V.F.Seg = 0;
|
||||
}
|
||||
|
||||
/* Add the assembler name of the symbol */
|
||||
SymSetAsmName (Entry);
|
||||
|
||||
/* Add the entry to the symbol table */
|
||||
AddSymEntry (Tab, Entry);
|
||||
}
|
||||
|
||||
/* If this is a function, do we wrap calls to it? */
|
||||
if (IsTypeFunc (Entry->Type)) {
|
||||
SymEntry* WrappedCall;
|
||||
unsigned int WrappedCallData;
|
||||
|
||||
/* Always use the latest wrapper data for it */
|
||||
GetWrappedCall ((void**)&WrappedCall, &WrappedCallData);
|
||||
if (WrappedCall) {
|
||||
Entry->V.F.WrappedCall = WrappedCall;
|
||||
Entry->V.F.WrappedCallData = WrappedCallData;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add an alias of the global symbol to the local symbol table */
|
||||
|
@ -22,23 +22,23 @@ void func3() {
|
||||
|
||||
}
|
||||
|
||||
#pragma wrapped-call(push, trampoline_inc, 0)
|
||||
|
||||
void func2() {
|
||||
func3();
|
||||
}
|
||||
|
||||
#pragma wrapped-call(push, trampoline_inc, 0)
|
||||
|
||||
void func2(void);
|
||||
|
||||
#pragma wrapped-call(push, trampoline_set, 4)
|
||||
|
||||
void func1(void);
|
||||
|
||||
#pragma wrapped-call(pop)
|
||||
#pragma wrapped-call(pop)
|
||||
|
||||
void func1(void) {
|
||||
func2();
|
||||
}
|
||||
|
||||
#pragma wrapped-call(pop)
|
||||
#pragma wrapped-call(pop)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
flag = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user