1 /*****************************************************************************/
5 /* Lightweight segment management stuff */
9 /* (C) 2001-2009, 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 /*****************************************************************************/
58 /*****************************************************************************/
60 /*****************************************************************************/
64 /* Pointer to the current segment list. Output goes here. */
67 /* Pointer to the global segment list */
70 /* Actual names for the segments */
71 static StrStack SegmentNames[SEG_COUNT];
73 /* We're using a collection for the stack instead of a linked list. Since
74 * functions may not be nested (at least in the current implementation), the
75 * maximum stack depth is 2, so there is not really a need for a better
78 static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER;
82 /*****************************************************************************/
84 /*****************************************************************************/
88 void InitSegNames (void)
89 /* Initialize the segment names */
91 SS_Push (&SegmentNames[SEG_BSS], SEGNAME_BSS);
92 SS_Push (&SegmentNames[SEG_CODE], SEGNAME_CODE);
93 SS_Push (&SegmentNames[SEG_DATA], SEGNAME_DATA);
94 SS_Push (&SegmentNames[SEG_RODATA], SEGNAME_RODATA);
99 void SetSegName (segment_t Seg, const char* Name)
100 /* Set a new name for a segment */
102 SS_Set (&SegmentNames[Seg], Name);
107 void PushSegName (segment_t Seg, const char* Name)
108 /* Push the current segment name and set a new name for a segment */
110 if (SS_IsFull (&SegmentNames[Seg])) {
111 Error ("Segment name stack overflow");
113 SS_Push (&SegmentNames[Seg], Name);
119 void PopSegName (segment_t Seg)
120 /* Restore a segment name from the segment name stack */
122 if (SS_GetCount (&SegmentNames[Seg]) < 2) {
123 Error ("Segment name stack is empty");
125 SS_Drop (&SegmentNames[Seg]);
131 const char* GetSegName (segment_t Seg)
132 /* Get the name of the given segment */
134 return SS_Get (&SegmentNames[Seg]);
139 static Segments* NewSegments (SymEntry* Func)
140 /* Initialize a Segments structure (set all fields to NULL) */
142 /* Allocate memory */
143 Segments* S = xmalloc (sizeof (Segments));
145 /* Initialize the fields */
146 S->Text = NewTextSeg (Func);
147 S->Code = NewCodeSeg (GetSegName (SEG_CODE), Func);
148 S->Data = NewDataSeg (GetSegName (SEG_DATA), Func);
149 S->ROData = NewDataSeg (GetSegName (SEG_RODATA), Func);
150 S->BSS = NewDataSeg (GetSegName (SEG_BSS), Func);
151 S->CurDSeg = SEG_DATA;
153 /* Return the new struct */
159 Segments* PushSegments (SymEntry* Func)
160 /* Make the new segment list current but remember the old one */
162 /* Push the current pointer onto the stack */
163 CollAppend (&SegmentStack, CS);
165 /* Create a new Segments structure */
166 CS = NewSegments (Func);
168 /* Return the new struct */
174 void PopSegments (void)
175 /* Pop the old segment list (make it current) */
177 /* Must have something on the stack */
178 PRECONDITION (CollCount (&SegmentStack) > 0);
180 /* Pop the last segment and set it as current */
181 CS = CollPop (&SegmentStack);
186 void CreateGlobalSegments (void)
187 /* Create the global segments and remember them in GS */
189 GS = PushSegments (0);
194 void UseDataSeg (segment_t DSeg)
195 /* For the current segment list, use the data segment DSeg */
197 /* Check the input */
198 PRECONDITION (CS && DSeg != SEG_CODE);
200 /* Set the new segment to use */
206 struct DataSeg* GetDataSeg (void)
207 /* Return the current data segment */
209 PRECONDITION (CS != 0);
210 switch (CS->CurDSeg) {
211 case SEG_BSS: return CS->BSS;
212 case SEG_DATA: return CS->Data;
213 case SEG_RODATA: return CS->ROData;
215 FAIL ("Invalid data segment");
222 void AddTextLine (const char* Format, ...)
223 /* Add a line of code to the current text segment */
226 va_start (ap, Format);
228 TS_AddVLine (CS->Text, Format, ap);
234 void AddCodeLine (const char* Format, ...)
235 /* Add a line of code to the current code segment */
238 va_start (ap, Format);
240 CS_AddVLine (CS->Code, CurTok.LI, Format, ap);
246 void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo)
247 /* Add a code entry to the current code segment */
250 CS_AddEntry (CS->Code, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI));
255 void AddDataLine (const char* Format, ...)
256 /* Add a line of data to the current data segment */
259 va_start (ap, Format);
261 DS_AddVLine (GetDataSeg(), Format, ap);
267 int HaveGlobalCode (void)
268 /* Return true if the global code segment contains entries (which is an error) */
270 return (CS_GetEntryCount (GS->Code) > 0);
275 void RemoveGlobalCode (void)
276 /* Remove all code from the global code segment. Used for error recovery. */
278 CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code));
283 void OutputSegments (const Segments* S)
284 /* Output the given segments to the output file */
286 /* Output the function prologue if the segments came from a function */
287 CS_OutputPrologue (S->Code);
289 /* Output the text segment */
292 /* Output the three data segments */
294 DS_Output (S->ROData);
297 /* Output the code segment */
300 /* Output the code segment epiloque */
301 CS_OutputEpilogue (S->Code);