/*****************************************************************************/
/* */
-/* stdfunc.c */
+/* stdfunc.c */
/* */
-/* Handle inlining of known functions for the cc65 compiler */
+/* Handle inlining of known functions for the cc65 compiler */
/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 1998-2010 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/*****************************************************************************/
-/* Function forwards */
+/* Function forwards */
/*****************************************************************************/
static void StdFunc_memcpy (FuncDesc*, ExprDesc*);
static void StdFunc_memset (FuncDesc*, ExprDesc*);
+static void StdFunc_strcmp (FuncDesc*, ExprDesc*);
static void StdFunc_strcpy (FuncDesc*, ExprDesc*);
static void StdFunc_strlen (FuncDesc*, ExprDesc*);
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
* alphabetically!
*/
static struct StdFuncDesc {
- const char* Name;
- void (*Handler) (FuncDesc*, ExprDesc*);
+ const char* Name;
+ void (*Handler) (FuncDesc*, ExprDesc*);
} StdFuncs[] = {
- { "memcpy", StdFunc_memcpy },
- { "memset", StdFunc_memset },
- { "strcpy", StdFunc_strcpy },
- { "strlen", StdFunc_strlen },
+ { "memcpy", StdFunc_memcpy },
+ { "memset", StdFunc_memset },
+ { "strcmp", StdFunc_strcmp },
+ { "strcpy", StdFunc_strcpy },
+ { "strlen", StdFunc_strlen },
};
-#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
+#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
typedef struct ArgDesc ArgDesc;
struct ArgDesc {
- const type* ArgType; /* Required argument type */
+ const Type* ArgType; /* Required argument type */
ExprDesc Expr; /* Argument expression */
- const type* Type; /* The original type before conversion */
- CodeMark Start; /* Start of the code for calculation */
+ const Type* Type; /* The original type before conversion */
+ CodeMark Load; /* Start of argument load code */
CodeMark Push; /* Start of argument push code */
CodeMark End; /* End of the code for calculation+push */
unsigned Flags; /* Code generation flags */
/*****************************************************************************/
-/* Helper functions */
+/* Helper functions */
/*****************************************************************************/
-static void ParseArg (ArgDesc* Arg, type* Type)
+static void ParseArg (ArgDesc* Arg, Type* Type)
/* Parse one argument but do not push it onto the stack. Make all fields in
* Arg valid.
*/
/* Remember the required argument type */
Arg->ArgType = Type;
- /* Remember the current code position */
- Arg->Start = GetCodePos ();
-
/* Read the expression we're going to pass to the function */
- ExprWithCheck (hie1, &Arg->Expr);
+ MarkedExprWithCheck (hie1, &Arg->Expr);
/* Remember the actual argument type */
Arg->Type = Arg->Expr.Type;
/* Convert this expression to the expected type */
TypeConversion (&Arg->Expr, Type);
+ /* Remember the following code position */
+ GetCodePos (&Arg->Load);
+
/* If the value is a constant, set the flag, otherwise load it into the
* primary register.
*/
- if (ED_IsConstAbsInt (&Arg->Expr)) {
+ if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) {
/* Remember that we have a constant value */
Arg->Flags |= CF_CONST;
} else {
}
/* Remember the following code position */
- Arg->End = Arg->Push = GetCodePos ();
+ GetCodePos (&Arg->Push);
+ GetCodePos (&Arg->End);
/* Use the type of the argument for the push */
Arg->Flags |= TypeOf (Arg->Expr.Type);
static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Handle the memcpy function */
{
- /* Argument types */
- static type Arg1Type[] = { T_PTR, T_VOID, T_END }; /* void* */
- static type Arg2Type[] = { T_PTR, T_VOID|T_QUAL_CONST, T_END }; /* const void* */
- static type Arg3Type[] = { T_SIZE_T, T_END }; /* size_t */
+ /* Argument types: (void*, const void*, size_t) */
+ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_VOID), TYPE(T_END) };
+ static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_VOID|T_QUAL_CONST), TYPE(T_END) };
+ static Type Arg3Type[] = { TYPE(T_SIZE_T), TYPE(T_END) };
- CodeMark Start;
ArgDesc Arg1, Arg2, Arg3;
unsigned ParamSize = 0;
unsigned Label;
-
- /* Remember where we are now */
- Start = GetCodePos ();
+ int Offs;
/* Argument #1 */
ParseArg (&Arg1, Arg1Type);
g_push (Arg1.Flags, Arg1.Expr.IVal);
- Arg1.End = GetCodePos ();
+ GetCodePos (&Arg1.End);
ParamSize += SizeOf (Arg1Type);
ConsumeComma ();
/* Argument #2 */
ParseArg (&Arg2, Arg2Type);
g_push (Arg2.Flags, Arg2.Expr.IVal);
- Arg2.End = GetCodePos ();
+ GetCodePos (&Arg2.End);
ParamSize += SizeOf (Arg2Type);
ConsumeComma ();
/* Remove all of the generated code but the load of the first
* argument, which is what memcpy returns.
*/
- RemoveCode (Arg1.Push);
+ RemoveCode (&Arg1.Push);
/* Set the function result to the first argument */
*Expr = Arg1.Expr;
int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need a label */
Label = GetLocalLabel ();
!(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
/* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ Offs = ED_GetStackOffs (&Arg1.Expr, 0);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need a label */
Label = GetLocalLabel ();
/* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127) {
+ if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
- if (Offs == 0 || AllowOneIndex) {
+ if (Offs == 0) {
AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
g_defcodelabel (Label);
AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
!(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
/* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+ Offs = ED_GetStackOffs (&Arg2.Expr, 0);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need a label */
Label = GetLocalLabel ();
/* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127) {
+ if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
- if (Offs == 0 || AllowOneIndex) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ if (Offs == 0) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
g_defcodelabel (Label);
AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
AddCodeLine ("dey");
AddCodeLine ("bpl %s", LocalLabelName (Label));
} else {
*/
*Expr = Arg1.Expr;
+ } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
+
+ /* Drop the generated code but leave the load of the first argument*/
+ RemoveCode (&Arg1.Push);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memcpy code */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ if (Arg3.Expr.IVal <= 127) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldy #$00");
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("iny");
+ AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
+
+ /* Reload result - X hasn't changed by the code above */
+ AddCodeLine ("lda ptr1");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
} else {
/* The function result is an rvalue in the primary register */
static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Handle the memset function */
{
- /* Argument types */
- static type Arg1Type[] = { T_PTR, T_VOID, T_END }; /* void* */
- static type Arg2Type[] = { T_INT, T_END }; /* int */
- static type Arg3Type[] = { T_SIZE_T, T_END }; /* size_t */
+ /* Argument types: (void*, int, size_t) */
+ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_VOID), TYPE(T_END) };
+ static Type Arg2Type[] = { TYPE(T_INT), TYPE(T_END) };
+ static Type Arg3Type[] = { TYPE(T_SIZE_T), TYPE(T_END) };
- CodeMark Start;
ArgDesc Arg1, Arg2, Arg3;
int MemSet = 1; /* Use real memset if true */
unsigned ParamSize = 0;
unsigned Label;
- /* Remember where we are now */
- Start = GetCodePos ();
-
/* Argument #1 */
ParseArg (&Arg1, Arg1Type);
g_push (Arg1.Flags, Arg1.Expr.IVal);
- Arg1.End = GetCodePos ();
+ GetCodePos (&Arg1.End);
ParamSize += SizeOf (Arg1Type);
ConsumeComma ();
} else {
/* Push the argument */
g_push (Arg2.Flags, Arg2.Expr.IVal);
- Arg2.End = GetCodePos ();
+ GetCodePos (&Arg2.End);
ParamSize += SizeOf (Arg2Type);
}
ConsumeComma ();
/* Remove all of the generated code but the load of the first
* argument, which is what memset returns.
*/
- RemoveCode (Arg1.Push);
+ RemoveCode (&Arg1.Push);
/* Set the function result to the first argument */
*Expr = Arg1.Expr;
int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need a label */
Label = GetLocalLabel ();
int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need a label */
Label = GetLocalLabel ();
/* Remove all of the generated code but the load of the first
* argument.
*/
- RemoveCode (Arg1.Push);
+ RemoveCode (&Arg1.Push);
/* We need a label */
Label = GetLocalLabel ();
+/*****************************************************************************/
+/* strcmp */
+/*****************************************************************************/
+
+
+
+static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
+/* Handle the strcmp function */
+{
+ /* Argument types: (const char*, const char*) */
+ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
+ static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
+
+ ArgDesc Arg1, Arg2;
+ unsigned ParamSize = 0;
+ long ECount1;
+ long ECount2;
+ int IsArray;
+ int Offs;
+
+ /* Setup the argument type string */
+ Arg1Type[1].C = GetDefaultChar () | T_QUAL_CONST;
+ Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
+
+ /* Argument #1 */
+ ParseArg (&Arg1, Arg1Type);
+ g_push (Arg1.Flags, Arg1.Expr.IVal);
+ ParamSize += SizeOf (Arg1Type);
+ ConsumeComma ();
+
+ /* Argument #2. */
+ ParseArg (&Arg2, Arg2Type);
+
+ /* Since strcmp is a fastcall function, we must load the
+ * arg into the primary if it is not already there. This parameter is
+ * also ignored for the calculation of the parameter size, since it is
+ * not passed via the stack.
+ */
+ if (Arg2.Flags & CF_CONST) {
+ LoadExpr (CF_NONE, &Arg2.Expr);
+ }
+
+ /* Emit the actual function call. This will also cleanup the stack. */
+ g_call (CF_FIXARGC, Func_strcmp, ParamSize);
+
+ /* Get the element counts of the arguments. Then get the larger of the
+ * two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically
+ */
+ ECount1 = ArrayElementCount (&Arg1);
+ ECount2 = ArrayElementCount (&Arg2);
+ if (ECount2 > ECount1) {
+ ECount1 = ECount2;
+ }
+
+ /* If the second argument is the empty string literal, we can generate
+ * more efficient code.
+ */
+ if (ED_IsLocLiteral (&Arg2.Expr) &&
+ IS_Get (&WritableStrings) == 0 &&
+ GetLiteralSize (Arg2.Expr.LVal) == 1 &&
+ GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
+
+ /* Drop the generated code so we have the first argument in the
+ * primary
+ */
+ RemoveCode (&Arg1.Push);
+
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg2.Expr.LVal);
+
+ /* We do now have Arg1 in the primary. Load the first character from
+ * this string and cast to int. This is the function result.
+ */
+ IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
+ if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
+
+ /* Generate code */
+ AddCodeLine ("ldy #$%02X", Offs);
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda (sp),y");
+ } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
+
+ /* Generate code */
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ /* Drop part of the generated code so we have the first argument
+ * in the primary
+ */
+ RemoveCode (&Arg1.Push);
+
+ /* Fetch the first char */
+ g_getind (CF_CHAR | CF_UNSIGNED, 0);
+ }
+
+ } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&InlineStdFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+
+
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Load;
+ const char* Compare;
+
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+
+ } else if ((IS_Get (&CodeSizeFactor) > 190) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ (IS_Get (&InlineStdFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+
+
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Compare;
+
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Push);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Store Arg1 into ptr1 */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine ("lda (ptr1),y");
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+
+ }
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ /* We expect the closing brace */
+ ConsumeRParen ();
+}
+
+
+
/*****************************************************************************/
/* strcpy */
/*****************************************************************************/
static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Handle the strcpy function */
{
- /* Argument types */
- static type Arg1Type[] = { T_PTR, T_CHAR, T_END }; /* char* */
- static type Arg2Type[] = { T_PTR, T_CHAR|T_QUAL_CONST, T_END }; /* const char* */
+ /* Argument types: (char*, const char*) */
+ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_CHAR), TYPE(T_END) };
+ static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
- CodeMark Start;
ArgDesc Arg1, Arg2;
unsigned ParamSize = 0;
long ECount;
unsigned L1;
/* Setup the argument type string */
- Arg1Type[1] = GetDefaultChar ();
- Arg2Type[1] = GetDefaultChar () | T_QUAL_CONST;
-
- /* Remember where we are now */
- Start = GetCodePos ();
+ Arg1Type[1].C = GetDefaultChar ();
+ Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
/* Argument #1 */
ParseArg (&Arg1, Arg1Type);
g_push (Arg1.Flags, Arg1.Expr.IVal);
- Arg1.End = GetCodePos ();
+ GetCodePos (&Arg1.End);
ParamSize += SizeOf (Arg1Type);
ConsumeComma ();
/* Emit the actual function call. This will also cleanup the stack. */
g_call (CF_FIXARGC, Func_strcpy, ParamSize);
- /* Get the element count of argument 2 if it is an array */
+ /* Get the element count of argument 1 if it is an array */
ECount = ArrayElementCount (&Arg1);
/* We've generated the complete code for the function now and know the
}
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need labels */
L1 = GetLocalLabel ();
int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need labels */
L1 = GetLocalLabel ();
int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
/* Drop the generated code */
- RemoveCode (Start);
+ RemoveCode (&Arg1.Expr.Start);
/* We need labels */
L1 = GetLocalLabel ();
static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Handle the strlen function */
{
- static type ArgType[] = { T_PTR, T_SCHAR, T_END };
+ static Type ArgType[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
ExprDesc Arg;
int IsArray;
int IsPtr;
/* Setup the argument type string */
- ArgType[1] = GetDefaultChar () | T_QUAL_CONST;
+ ArgType[1].C = GetDefaultChar () | T_QUAL_CONST;
/* Evaluate the parameter */
hie1 (&Arg);
if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
/* Constant string literal */
- ED_MakeConstAbs (Expr, strlen (GetLiteral (Arg.IVal)), type_size_t);
- ResetLiteralPoolOffs (Arg.IVal);
+ ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
+
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg.LVal);
/* We will inline strlen for arrays with constant addresses, if either the
* inlining was forced on the command line, or the array is smaller than
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
/* Call the handler function */
D->Handler (F, lval);
}
-
-
-