1 /*****************************************************************************/
5 /* Unnamed labels for the ca65 macroassembler */
9 /* (C) 2000-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* Struct that describes an unnamed label */
57 typedef struct ULabel ULabel;
59 Collection LineInfos; /* Position of the label in the source */
60 ExprNode* Val; /* The label value - may be NULL */
61 unsigned Ref; /* Number of references */
65 static Collection ULabList = STATIC_COLLECTION_INITIALIZER;
66 static unsigned ULabDefCount = 0; /* Number of defined labels */
70 /*****************************************************************************/
72 /*****************************************************************************/
76 static ULabel* NewULabel (ExprNode* Val)
77 /* Create a new ULabel and insert it into the collection. The created label
78 * structure is returned.
81 /* Allocate memory for the ULabel structure */
82 ULabel* L = xmalloc (sizeof (ULabel));
84 /* Initialize the fields */
85 L->LineInfos = EmptyCollection;
86 GetFullLineInfo (&L->LineInfos);
90 /* Insert the label into the collection */
91 CollAppend (&ULabList, L);
93 /* Return the created label */
99 ExprNode* ULabRef (int Which)
100 /* Get an unnamed label. If Which is negative, it is a backreference (a
101 * reference to an already defined label), and the function will return a
102 * segment relative expression. If Which is positive, it is a forward ref,
103 * and the function will return a expression node for an unnamed label that
104 * must be resolved later.
110 /* Which can never be 0 */
111 PRECONDITION (Which != 0);
113 /* Get the index of the referenced label */
117 Index = (int) ULabDefCount + Which;
119 /* We cannot have negative label indices */
121 /* Label does not exist */
122 Error ("Undefined label");
123 /* We must return something valid */
124 return GenCurrentPC();
127 /* Check if the label exists. If not, generate enough forward labels. */
128 if (Index < (int) CollCount (&ULabList)) {
129 /* The label exists, get it. */
130 L = CollAtUnchecked (&ULabList, Index);
132 /* Generate new, undefined labels */
133 while (Index >= (int) CollCount (&ULabList)) {
138 /* Mark the label as referenced */
141 /* If the label is already defined, return its value, otherwise return
145 return CloneExpr (L->Val);
147 return GenULabelExpr (Index);
154 /* Define an unnamed label at the current PC */
156 if (ULabDefCount < CollCount (&ULabList)) {
157 /* We did already have a forward reference to this label, so has
158 * already been generated, but doesn't have a value. Use the current
159 * PC for the label value.
161 ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
163 L->Val = GenCurrentPC ();
164 CollDeleteAll (&L->LineInfos);
165 GetFullLineInfo (&L->LineInfos);
167 /* There is no such label, create it */
168 NewULabel (GenCurrentPC ());
171 /* We have one more defined label */
177 int ULabCanResolve (void)
178 /* Return true if we can resolve arbitrary ULabels. */
180 /* We can resolve labels if we don't have any undefineds */
181 return (ULabDefCount == CollCount (&ULabList));
186 ExprNode* ULabResolve (unsigned Index)
187 /* Return a valid expression for the unnamed label with the given index. This
188 * is used to resolve unnamed labels when assembly is done, so it is an error
189 * if a label is still undefined in this phase.
192 /* Get the label and check that it is defined */
193 ULabel* L = CollAt (&ULabList, Index);
196 /* Return the label value */
197 return CloneExpr (L->Val);
202 void ULabCheck (void)
203 /* Run through all unnamed labels and check for anomalies and errors */
205 /* Check if there are undefined labels */
206 unsigned I = ULabDefCount;
207 while (I < CollCount (&ULabList)) {
208 ULabel* L = CollAtUnchecked (&ULabList, I);
209 LIError (&L->LineInfos, "Undefined label");
213 /* Walk over all labels and emit a warning if any unreferenced ones
216 for (I = 0; I < CollCount (&ULabList); ++I) {
217 ULabel* L = CollAtUnchecked (&ULabList, I);
219 LIWarning (&L->LineInfos, 1, "No reference to unnamed label");