/*****************************************************************************/
-/* Line Collections */
+/* Line Collections */
/*****************************************************************************/
+static int IsExtLabel (const Line* L)
+/* Return true if the line is an external label line */
+{
+ return (L->Line [0] == '_');
+}
+
+
+
static int IsLabel (const Line* L)
/* Return true if the line is a label line */
{
L = GetTargetLine (L->Line+5);
}
- /* Get the next instruction line */
- L = NextInstruction (L);
+ /* Get the next line, skip local labels */
+ do {
+ L = NextCodeSegLine (L);
+ } while (L && (IsLocalLabel (L) || L->Line[0] == '\0'));
/* Bail out if we're done */
- if (L == 0 || IsLabel (L)) {
- /* Something is wrong */
- return REG_ALL;
+ if (L == 0 || IsExtLabel (L)) {
+ /* End of function reached */
+ goto ExitPoint;
}
/* Check if we had this line already. If so, bail out, if not,
} while (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL"));
+ /* Special handling of code hints */
+ if (IsHintLine (L)) {
+
+ if (IsHint (L, "a:-") && (Used & REG_A) == 0) {
+ Unused |= REG_A;
+ } else if (IsHint (L, "x:-") && (Used & REG_X) == 0) {
+ Unused |= REG_X;
+ } else if (IsHint (L, "y:-") && (Used & REG_Y) == 0) {
+ Unused |= REG_Y;
+ }
+
/* Special handling for branches */
- if (LineMatchX (L, ShortBranches) >= 0 ||
+ } else if (LineMatchX (L, ShortBranches) >= 0 ||
LineMatchX (L, LongBranches) >= 0) {
const char* Target = L->Line+5;
if (Target[0] == 'L') {
- /* Jump to local label. Check the register usage starting at
- * the branch target and at the code following the branch.
- * All registers that are unused in both execution flows are
- * returned as unused.
- */
- unsigned U1, U2;
+ /* Jump to local label. Check the register usage starting at
+ * the branch target and at the code following the branch.
+ * All registers that are unused in both execution flows are
+ * returned as unused.
+ */
+ unsigned U1, U2;
U2 = RVUInt1 (GetTargetLine (Target), LC, Used, Unused);
- U1 = RVUInt1 (L, LC, Used, Unused);
- return U1 | U2; /* Used in any of the branches */
+ U1 = RVUInt1 (L, LC, Used, Unused);
+ return U1 | U2; /* Used in any of the branches */
}
- }
+ } else {
- /* Search for the instruction in this line */
- I = FindCmd (L);
+ /* Search for the instruction in this line */
+ I = FindCmd (L);
- /* If we don't find it, assume all other registers are */
- if (I < 0) {
- break;
- }
+ /* If we don't find it, assume all other registers are used */
+ if (I < 0) {
+ break;
+ }
- /* Evaluate the use flags, check for addressing modes */
- R = CmdDesc[I].Use;
- if (IsXAddrMode (L)) {
- R |= REG_X;
- } else if (IsYAddrMode (L)) {
- R |= REG_Y;
- }
- if (R) {
- /* Remove registers that were already new loaded */
- R &= ~Unused;
+ /* Evaluate the use flags, check for addressing modes */
+ R = CmdDesc[I].Use;
+ if (IsXAddrMode (L)) {
+ R |= REG_X;
+ } else if (IsYAddrMode (L)) {
+ R |= REG_Y;
+ }
+ if (R) {
+ /* Remove registers that were already new loaded */
+ R &= ~Unused;
- /* Remember the remaining registers */
- Used |= R;
- }
+ /* Remember the remaining registers */
+ Used |= R;
+ }
- /* Evaluate the load flags */
- R = CmdDesc[I].Load;
- if (R) {
- /* Remove registers that were already used */
- R &= ~Used;
+ /* Evaluate the load flags */
+ R = CmdDesc[I].Load;
+ if (R) {
+ /* Remove registers that were already used */
+ R &= ~Used;
- /* Remember the remaining registers */
- Unused |= R;
- }
+ /* Remember the remaining registers */
+ Unused |= R;
+ }
+
+ }
/* If we know about all registers, bail out */
if ((Used | Unused) == REG_ALL) {
/* Handle 'return' statement here */
{
struct expent lval;
- unsigned etype = 0; /* Type of return expression */
+ unsigned Flags = 0; /* Code generator flags */
int HaveVal = 0; /* Do we have a return value in ax? */
}
if (evalexpr (CF_NONE, hie0, &lval) == 0) {
/* Constant value */
- etype = CF_CONST;
+ Flags = CF_CONST;
} else {
- /* Value in the primary register */
- HaveVal = 1;
- }
+ /* Value in the primary register */
+ HaveVal = 1;
+ }
- /* Convert the return value to the type of the function result */
- if (!HasVoidReturn (CurrentFunc)) {
- etype |= assignadjust (GetReturnType (CurrentFunc), &lval) & ~CF_CONST;
- }
+ /* Convert the return value to the type of the function result */
+ if (!HasVoidReturn (CurrentFunc)) {
+ Flags |= (assignadjust (GetReturnType (CurrentFunc), &lval) & ~CF_CONST) | CF_REG;
+ }
} else if (!HasVoidReturn (CurrentFunc)) {
- Error ("Function `%s' must return a value", GetFuncName (CurrentFunc));
+ Error ("Function `%s' must return a value", GetFuncName (CurrentFunc));
}
RestoreRegVars (HaveVal);
- g_leave (etype, lval.e_const);
+ g_leave (Flags, lval.e_const);
}
CodeLab = GetLabel ();
}
g_jump (CodeLab);
- }
+ }
/* Remember that we had a default label */
HaveDefault = 1;