Use a dedicated label pool for literals.
This commit is contained in:
@@ -98,3 +98,32 @@ int IsLocalLabelName (const char* Name)
|
|||||||
/* Local label name */
|
/* Local label name */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned GetPooledLiteralLabel (void)
|
||||||
|
/* Get an unused literal label. Will never return zero. */
|
||||||
|
{
|
||||||
|
/* Number to generate unique labels */
|
||||||
|
static unsigned NextLabel = 0;
|
||||||
|
|
||||||
|
/* Check for an overflow */
|
||||||
|
if (NextLabel >= 0xFFFF) {
|
||||||
|
Internal ("Literal label overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the next label */
|
||||||
|
return ++NextLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* PooledLiteralLabelName (unsigned L)
|
||||||
|
/* Make a litral label name from the given label number. The label name will be
|
||||||
|
** created in static storage and overwritten when calling the function again.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
static char Buf[64];
|
||||||
|
sprintf (Buf, "S%04X", L);
|
||||||
|
return Buf;
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ const char* LocalLabelName (unsigned L);
|
|||||||
int IsLocalLabelName (const char* Name);
|
int IsLocalLabelName (const char* Name);
|
||||||
/* Return true if Name is the name of a local label */
|
/* Return true if Name is the name of a local label */
|
||||||
|
|
||||||
|
unsigned GetPooledLiteralLabel (void);
|
||||||
|
/* Get an unused literal label. Will never return zero. */
|
||||||
|
|
||||||
|
const char* PooledLiteralLabelName (unsigned L);
|
||||||
|
/* Make a litral label name from the given label number. The label name will be
|
||||||
|
** created in static storage and overwritten when calling the function again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of asmlabel.h */
|
/* End of asmlabel.h */
|
||||||
|
|||||||
@@ -124,6 +124,16 @@ static const char* GetLabelName (unsigned Flags, uintptr_t Label, long Offs)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CF_LITERAL:
|
||||||
|
/* Literal */
|
||||||
|
/* Static memory cell */
|
||||||
|
if (Offs) {
|
||||||
|
xsprintf (Buf, sizeof (Buf), "%s%+ld", PooledLiteralLabelName (Label), Offs);
|
||||||
|
} else {
|
||||||
|
xsprintf (Buf, sizeof (Buf), "%s", PooledLiteralLabelName (Label));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case CF_ABSOLUTE:
|
case CF_ABSOLUTE:
|
||||||
/* Absolute address */
|
/* Absolute address */
|
||||||
xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Label+Offs) & 0xFFFF));
|
xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Label+Offs) & 0xFFFF));
|
||||||
@@ -355,24 +365,6 @@ void g_defdatalabel (unsigned label)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs)
|
|
||||||
/* Define label as a local alias for baselabel+offs */
|
|
||||||
{
|
|
||||||
/* We need an intermediate buffer here since LocalLabelName uses a
|
|
||||||
** static buffer which changes with each call.
|
|
||||||
*/
|
|
||||||
StrBuf L = AUTO_STRBUF_INITIALIZER;
|
|
||||||
SB_AppendStr (&L, LocalLabelName (label));
|
|
||||||
SB_Terminate (&L);
|
|
||||||
AddDataLine ("%s\t:=\t%s+%ld",
|
|
||||||
SB_GetConstBuf (&L),
|
|
||||||
LocalLabelName (baselabel),
|
|
||||||
offs);
|
|
||||||
SB_Done (&L);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Functions handling global labels */
|
/* Functions handling global labels */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -388,6 +380,33 @@ void g_defgloblabel (const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void g_defliterallabel (unsigned label)
|
||||||
|
/* Define a literal data label */
|
||||||
|
{
|
||||||
|
/* Literal labels are always data labels */
|
||||||
|
AddDataLine ("%s:", PooledLiteralLabelName (label));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void g_aliasliterallabel (unsigned label, unsigned baselabel, long offs)
|
||||||
|
/* Define label as an alias for baselabel+offs */
|
||||||
|
{
|
||||||
|
/* We need an intermediate buffer here since LocalLabelName uses a
|
||||||
|
** static buffer which changes with each call.
|
||||||
|
*/
|
||||||
|
StrBuf L = AUTO_STRBUF_INITIALIZER;
|
||||||
|
SB_AppendStr (&L, PooledLiteralLabelName (label));
|
||||||
|
SB_Terminate (&L);
|
||||||
|
AddDataLine ("%s\t:=\t%s+%ld",
|
||||||
|
SB_GetConstBuf (&L),
|
||||||
|
PooledLiteralLabelName (baselabel),
|
||||||
|
offs);
|
||||||
|
SB_Done (&L);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void g_defexport (const char* Name, int ZP)
|
void g_defexport (const char* Name, int ZP)
|
||||||
/* Export the given label */
|
/* Export the given label */
|
||||||
{
|
{
|
||||||
@@ -2364,7 +2383,7 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize)
|
|||||||
void g_callind (unsigned Flags, unsigned ArgSize, int Offs)
|
void g_callind (unsigned Flags, unsigned ArgSize, int Offs)
|
||||||
/* Call subroutine indirect */
|
/* Call subroutine indirect */
|
||||||
{
|
{
|
||||||
if ((Flags & CF_STACK) == 0) {
|
if ((Flags & CF_ADDRMASK) != CF_STACK) {
|
||||||
/* Address is in a/x */
|
/* Address is in a/x */
|
||||||
if ((Flags & CF_FIXARGC) == 0) {
|
if ((Flags & CF_FIXARGC) == 0) {
|
||||||
/* Pass arg count */
|
/* Pass arg count */
|
||||||
|
|||||||
@@ -148,9 +148,6 @@ void g_defcodelabel (unsigned label);
|
|||||||
void g_defdatalabel (unsigned label);
|
void g_defdatalabel (unsigned label);
|
||||||
/* Define a local data label */
|
/* Define a local data label */
|
||||||
|
|
||||||
void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs);
|
|
||||||
/* Define label as a local alias for baselabel+offs */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -162,6 +159,12 @@ void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs);
|
|||||||
void g_defgloblabel (const char* Name);
|
void g_defgloblabel (const char* Name);
|
||||||
/* Define a global label with the given name */
|
/* Define a global label with the given name */
|
||||||
|
|
||||||
|
void g_defliterallabel (unsigned label);
|
||||||
|
/* Define a literal data label */
|
||||||
|
|
||||||
|
void g_aliasliterallabel (unsigned label, unsigned baselabel, long offs);
|
||||||
|
/* Define label as an alias for baselabel+offs */
|
||||||
|
|
||||||
void g_defexport (const char* Name, int ZP);
|
void g_defexport (const char* Name, int ZP);
|
||||||
/* Export the given label */
|
/* Export the given label */
|
||||||
|
|
||||||
|
|||||||
@@ -2185,11 +2185,15 @@ static void DefineData (ExprDesc* Expr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case E_LOC_STATIC:
|
case E_LOC_STATIC:
|
||||||
case E_LOC_LITERAL:
|
/* Static variable */
|
||||||
/* Static variable or literal in the literal pool */
|
|
||||||
g_defdata (CF_STATIC, Expr->Name, Expr->IVal);
|
g_defdata (CF_STATIC, Expr->Name, Expr->IVal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case E_LOC_LITERAL:
|
||||||
|
/* Literal in the literal pool */
|
||||||
|
g_defdata (CF_LITERAL, Expr->Name, Expr->IVal);
|
||||||
|
break;
|
||||||
|
|
||||||
case E_LOC_REGISTER:
|
case E_LOC_REGISTER:
|
||||||
/* Register variable. Taking the address is usually not
|
/* Register variable. Taking the address is usually not
|
||||||
** allowed.
|
** allowed.
|
||||||
|
|||||||
@@ -190,9 +190,9 @@ const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
|
|||||||
case E_LOC_LITERAL:
|
case E_LOC_LITERAL:
|
||||||
/* Literal in the literal pool */
|
/* Literal in the literal pool */
|
||||||
if (Offs) {
|
if (Offs) {
|
||||||
SB_Printf (&Buf, "%s%+ld", LocalLabelName (Expr->Name), Offs);
|
SB_Printf (&Buf, "%s%+ld", PooledLiteralLabelName (Expr->Name), Offs);
|
||||||
} else {
|
} else {
|
||||||
SB_Printf (&Buf, "%s", LocalLabelName (Expr->Name));
|
SB_Printf (&Buf, "%s", PooledLiteralLabelName (Expr->Name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ static Literal* NewLiteral (const void* Buf, unsigned Len)
|
|||||||
Literal* L = xmalloc (sizeof (*L));
|
Literal* L = xmalloc (sizeof (*L));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
L->Label = GetLocalLabel ();
|
L->Label = GetPooledLiteralLabel ();
|
||||||
L->RefCount = 0;
|
L->RefCount = 0;
|
||||||
L->Output = 0;
|
L->Output = 0;
|
||||||
SB_Init (&L->Data);
|
SB_Init (&L->Data);
|
||||||
@@ -130,7 +130,7 @@ static void OutputLiteral (Literal* L)
|
|||||||
TranslateLiteral (L);
|
TranslateLiteral (L);
|
||||||
|
|
||||||
/* Define the label for the literal */
|
/* Define the label for the literal */
|
||||||
g_defdatalabel (L->Label);
|
g_defliterallabel (L->Label);
|
||||||
|
|
||||||
/* Output the literal data */
|
/* Output the literal data */
|
||||||
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
|
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
|
||||||
@@ -423,12 +423,12 @@ static void OutputReadOnlyLiterals (Collection* Literals)
|
|||||||
if (C != 0) {
|
if (C != 0) {
|
||||||
|
|
||||||
/* This literal is part of a longer literal, merge them */
|
/* This literal is part of a longer literal, merge them */
|
||||||
g_aliasdatalabel (L->Label, C->Label, GetLiteralSize (C) - GetLiteralSize (L));
|
g_aliasliterallabel (L->Label, C->Label, GetLiteralSize (C) - GetLiteralSize (L));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Define the label for the literal */
|
/* Define the label for the literal */
|
||||||
g_defdatalabel (L->Label);
|
g_defliterallabel (L->Label);
|
||||||
|
|
||||||
/* Output the literal data */
|
/* Output the literal data */
|
||||||
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
|
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
|
||||||
|
|||||||
@@ -64,11 +64,15 @@ static void LoadAddress (unsigned Flags, ExprDesc* Expr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case E_LOC_STATIC:
|
case E_LOC_STATIC:
|
||||||
case E_LOC_LITERAL:
|
/* Static symbol, load address */
|
||||||
/* Static symbol or literal, load address */
|
|
||||||
g_getimmed ((Flags | CF_STATIC) & ~CF_CONST, Expr->Name, Expr->IVal);
|
g_getimmed ((Flags | CF_STATIC) & ~CF_CONST, Expr->Name, Expr->IVal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case E_LOC_LITERAL:
|
||||||
|
/* Literal, load address */
|
||||||
|
g_getimmed ((Flags | CF_LITERAL) & ~CF_CONST, Expr->Name, Expr->IVal);
|
||||||
|
break;
|
||||||
|
|
||||||
case E_LOC_REGISTER:
|
case E_LOC_REGISTER:
|
||||||
/* Register variable. Taking the address is usually not
|
/* Register variable. Taking the address is usually not
|
||||||
** allowed.
|
** allowed.
|
||||||
@@ -183,11 +187,15 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case E_LOC_STATIC:
|
case E_LOC_STATIC:
|
||||||
case E_LOC_LITERAL:
|
/* Static variable */
|
||||||
/* Static variable or literal in the literal pool */
|
|
||||||
g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal);
|
g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case E_LOC_LITERAL:
|
||||||
|
/* Literal in the literal pool */
|
||||||
|
g_getstatic (Flags | CF_LITERAL, Expr->Name, Expr->IVal);
|
||||||
|
break;
|
||||||
|
|
||||||
case E_LOC_REGISTER:
|
case E_LOC_REGISTER:
|
||||||
/* Register variable */
|
/* Register variable */
|
||||||
g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal);
|
g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal);
|
||||||
|
|||||||
Reference in New Issue
Block a user