summaryrefslogtreecommitdiff
path: root/misc/pascal/insn32/plopt/pfopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/pascal/insn32/plopt/pfopt.c')
-rw-r--r--misc/pascal/insn32/plopt/pfopt.c543
1 files changed, 543 insertions, 0 deletions
diff --git a/misc/pascal/insn32/plopt/pfopt.c b/misc/pascal/insn32/plopt/pfopt.c
new file mode 100644
index 000000000..de07400bf
--- /dev/null
+++ b/misc/pascal/insn32/plopt/pfopt.c
@@ -0,0 +1,543 @@
+/**********************************************************************
+ * pfopt.c
+ * Finalization of optimized image
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **********************************************************************/
+
+/**********************************************************************
+ * Included Files
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "keywords.h"
+#include "pdefs.h"
+#include "podefs.h"
+#include "pedefs.h"
+#include "pinsn32.h"
+#include "poff.h"
+
+#include "paslib.h"
+#include "pofflib.h"
+#include "popt.h"
+#include "pfopt.h"
+#include "pinsn.h"
+#include "perr.h"
+
+/**********************************************************************
+ * Definitions
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Types
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Data
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Function Prototypes
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Inline Functions
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Functions
+ **********************************************************************/
+
+/**********************************************************************/
+
+static void pass1(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle)
+{
+ OPTYPE op;
+ uint32 pc;
+ int opsize;
+ int fileno = 0;
+
+ /* Build label / line number reference table
+ *
+ * CASE 1: LABEL
+ * Add label number + PC to table
+ * discard
+ * CASE 2: LINE
+ * genereate a line number reference
+ * discard
+ * ELSE:
+ * pass through with no additional action
+ */
+
+ pc = 0;
+ do
+ {
+ opsize = insn_GetOpCode(poffHandle, &op);
+ if (GETOP(&op) == oLABEL)
+ {
+ poffAddToDefinedLabelTable(GETARG(&op), pc);
+ }
+ else if (GETOP(&op) == oINCLUDE)
+ {
+ fileno = GETARG(&op);
+ }
+ else if (GETOP(&op) == oLINE)
+ {
+ poffAddLineNumber(poffHandle, GETARG(&op), fileno, pc);
+ }
+ else
+ {
+ insn_AddTmpOpCode(poffProgHandle, &op);
+ pc += opsize;
+ }
+ }
+ while (GETOP(&op) != oEND);
+
+ /* Replace the original program data with the new program data */
+
+ poffReplaceProgData(poffHandle, poffProgHandle);
+}
+
+/**********************************************************************/
+
+static void pass2(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle)
+{
+ poffSymHandle_t poffSymHandle;
+ sint32 symIndex;
+ sint32 nchanges = 0;
+
+ /* Get a container to temporarily hold any modifications that we
+ * make to the symbol table.
+ */
+
+ poffSymHandle = poffCreateSymHandle();
+ if (poffSymHandle == NULL)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ /* Now read all of the symbols. (1) Add each undefined code reference
+ * to the label reference table, and (2) Change each defined code
+ * reference from a label to a program data section offset.
+ */
+
+ do
+ {
+ poffLibSymbol_t symbol;
+ symIndex = poffGetSymbol(poffHandle, &symbol);
+ if (symIndex >= 0)
+ {
+ if ((symbol.type == STT_PROC) || (symbol.type == STT_FUNC))
+ {
+ /* It is a symbol associated with the program data section.
+ * Has is value been defined?
+ */
+
+ if ((symbol.flags & STF_UNDEFINED) != 0)
+ {
+ /* No... Add it to the list of undefined labels */
+
+ poffAddToUndefinedLabelTable(symbol.value, symIndex);
+ }
+ else
+ {
+ /* It is a defined symbol. In this case, we should have
+ * encountered its LABEL marker in the pass1 processing
+ * and the following look up should not fail.
+ */
+ sint32 value = poffGetPcForDefinedLabel(symbol.value);
+ if (value < 0)
+ {
+ DEBUG(stdout, "Failed to find label L%04lx\n", symbol.value);
+ fatal(ePOFFCONFUSION);
+ }
+ else
+ {
+ /* Replace the lavel value with the section offset
+ * (pc) value.
+ */
+
+ symbol.value = value;
+ nchanges++;
+ }
+ }
+ }
+
+ /* In either event, we will want to save the symbol in case
+ * we need to re-write the symbol table.
+ */
+
+ (void)poffAddTmpSymbol(poffHandle, poffSymHandle, &symbol);
+ }
+ }
+ while (symIndex >= 0);
+
+ /* We any changes made to the symbol table in the temporary container? */
+
+ if (nchanges != 0)
+ {
+ /* Yes, update the symbol table */
+
+ poffReplaceSymbolTable(poffHandle, poffSymHandle);
+
+ }
+
+ /* Release the symbol container. */
+
+ poffDestroySymHandle(poffSymHandle);
+}
+
+/**********************************************************************/
+
+static void pass3(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle)
+{
+ OPTYPE op;
+ uint32 pc;
+ uint32 opsize;
+
+ /* Read each opcode, generate relocation information and
+ * replace label references with program section offsets.
+ *
+ * CASE 1: LAC
+ * generate RODATA relocation entry
+ * CASE 2: PCAL instructions
+ * replace label with I-space offset, OR
+ * generate a PROGRAM relocation entry
+ * CASE 3: J* instructions
+ * replace label with I-space offset
+ * CASE 4: LDS*, STS*, and LAS* instructions
+ * generate a STACK relocation (if imported?)
+ * ELSE:
+ * pass through with no additional action
+ */
+
+ pc = 0;
+ do
+ {
+ opsize = insn_GetOpCode(poffHandle, &op);
+ switch (GETOP(&op))
+ {
+ /* Load of an address in the rodata section */
+
+ case oLAC:
+ /* We are referencing something from the rodata section.
+ * No special action need be taken.
+ */
+ break;
+
+ /* Call to a procedure or function. */
+
+ case oPCAL:
+ {
+ /* Check if this is a defined label, i.e., a call to
+ * procedure or function in the same file.
+ */
+
+ sint32 value = poffGetPcForDefinedLabel(GETARG(&op));
+ if (value >= 0)
+ {
+ /* Yes... replace the label reference with
+ * a text section offset. No relocation record
+ * is needed in this case. The only relocation
+ * may be performed is a subsequent program data
+ * section offset.
+ */
+
+ PUTARG(&op, value);
+ }
+ else
+ {
+ /* Check if this is a undefined label. This would
+ * occur for a call to a procedure or a function that
+ * is defined in some other unit file.
+ */
+
+ value = poffGetSymIndexForUndefinedLabel(GETARG(&op));
+ if (value >= 0)
+ {
+ /* Use the value zero now */
+
+ PUTARG(&op, 0);
+
+ /* And generate a symbol-based relocation */
+
+ (void)poffAddRelocation(poffHandle, RLT_PCAL, value, pc);
+ }
+ else
+ {
+ DEBUG(stdout, "Failed to find call label L%04x\n",
+ GETARG(&op));
+ fatal(ePOFFCONFUSION);
+ }
+ }
+ }
+ break;
+
+ /* Jumps to "nearby" addresses */
+
+ case oJMP: /* Unconditional */
+ case oJEQUZ: /* Unary comparisons with zero */
+ case oJNEQZ:
+ case oJLTZ:
+ case oJGTEZ:
+ case oJGTZ:
+ case oJLTEZ:
+ case oJEQU: /* Binary comparisons */
+ case oJNEQ:
+ case oJLT:
+ case oJGTE:
+ case oJGT:
+ case oJLTE:
+ {
+ /* Check if this is a defined label. This must be the case
+ * because there can be no jumps into a unit file.
+ */
+
+ sint32 value = poffGetPcForDefinedLabel(GETARG(&op));
+ if (value >= 0)
+ {
+ /* Yes... replace the label reference with
+ * a text section offset. No relocation record
+ * is needed in this case. The only relocation
+ * may be performed is a subsequent program data
+ * sectioin offset.
+ */
+
+ PUTARG(&op, value);
+ }
+ else
+ {
+ DEBUG(stdout, "Failed to find jump label L%04x\n",
+ GETARG(&op));
+ fatal(ePOFFCONFUSION);
+ }
+ }
+ break;
+
+ /* References to stack via level offset */
+
+ case oLAS: /* Load stack address */
+ case oLASX:
+ case oLDS: /* Load value */
+ case oLDSH:
+ case oLDSB:
+ case oLDSM:
+ case oSTS: /* Store value */
+ case oSTSH:
+ case oSTSB:
+ case oSTSM:
+ case oLDSX:
+ case oLDSXH: /* Load value indexed */
+ case oLDSXB:
+ case oLDSXM:
+ case oSTSX: /* Store value indexed */
+ case oSTSXH:
+ case oSTSXB:
+ case oSTSXM:
+ {
+#warning REVISIT
+ }
+ break;
+
+ /* Otherwise, it is not an interesting opcode */
+ default:
+ break;
+ }
+
+ /* Save the potentially modified opcode in the temporary
+ * program data container.
+ */
+
+ insn_AddTmpOpCode(poffProgHandle, &op);
+ pc += opsize;
+ }
+ while (GETOP(&op) != oEND);
+
+ /* Replace the original program data with the new program data */
+
+ poffReplaceProgData(poffHandle, poffProgHandle);
+}
+
+/**********************************************************************/
+/* Fixed label references in the debug function information */
+
+static void pass4(poffHandle_t poffHandle)
+{
+ poffLibDebugFuncInfo_t *pDebugInfoHead = NULL;
+ poffLibDebugFuncInfo_t *pDebugInfoTail = NULL;
+ poffLibDebugFuncInfo_t *pDebugInfo;
+ poffLibDebugFuncInfo_t *pNextDebugInfo;
+
+ /* Read all function debug information into a link list */
+
+ while ((pDebugInfo = poffGetDebugFuncInfo(poffHandle)) != NULL)
+ {
+ if (!pDebugInfoHead)
+ {
+ pDebugInfoHead = pDebugInfo;
+ }
+ else
+ {
+ pDebugInfoTail->next = pDebugInfo;
+ }
+ pDebugInfoTail = pDebugInfo;
+ }
+
+ /* Convert all of the label references to pcode offsets */
+
+ for (pDebugInfo = pDebugInfoHead; pDebugInfo; pDebugInfo = pDebugInfo->next)
+ {
+ /* Check if this is a defined label. This must be the case
+ * because there can be no jumps into a unit file.
+ */
+
+ sint32 value = poffGetPcForDefinedLabel(pDebugInfo->value);
+ if (value >= 0)
+ {
+ /* Yes... replace the label reference with a text section offset. */
+
+ pDebugInfo->value = value;
+ }
+ else
+ {
+ fatal(ePOFFCONFUSION);
+ }
+ }
+
+ /* Then put all of the debug info back into the POFF object */
+
+ poffDiscardDebugFuncInfo(poffHandle);
+
+ for (pDebugInfo = pDebugInfoHead; pDebugInfo; pDebugInfo = pDebugInfo->next)
+ {
+ poffAddDebugFuncInfo(poffHandle, pDebugInfo);
+ }
+
+ /* Release the bufferred debug information */
+
+ pDebugInfo = pDebugInfoHead;
+ while (pDebugInfo)
+ {
+ pNextDebugInfo = pDebugInfo->next;
+ poffReleaseDebugFuncContainer(pDebugInfo);
+ pDebugInfo = pNextDebugInfo;
+ }
+}
+
+/**********************************************************************/
+
+static void pass5(poffHandle_t poffHandle)
+{
+ uint32 entryLabel;
+ sint32 entryOffset;
+ ubyte fileType;
+
+ /* What kind of a file did we just process. Was it a program file?
+ * or was it a unit file?
+ */
+
+ fileType = poffGetFileType(poffHandle);
+ if (fileType == FHT_PROGRAM)
+ {
+ /* It is a program file. In this case, it must have a valid
+ * entry point label. Get it.
+ */
+
+ entryLabel = poffGetEntryPoint(poffHandle);
+
+ /* Convert the label into a program data section offset */
+
+ entryOffset = poffGetPcForDefinedLabel(entryLabel);
+ if (entryOffset < 0)
+ {
+ fatal(ePOFFCONFUSION);
+ }
+
+ /* Replace file header entry point with the program data
+ * section offset
+ */
+
+ poffSetEntryPoint(poffHandle, entryOffset);
+ }
+}
+
+/**********************************************************************
+ * Global Functions
+ **********************************************************************/
+
+void optFinalize(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle)
+{
+ /* Build label / line number reference table */
+
+ pass1(poffHandle, poffProgHandle);
+
+ /* Reset for next pass */
+
+ insn_ResetOpCodeRead(poffHandle);
+ insn_ResetTmpOpCodeWrite(poffProgHandle);
+
+ /* Now process all of the symbols */
+
+ pass2(poffHandle, poffProgHandle);
+
+ /* Reset for next pass */
+
+ insn_ResetOpCodeRead(poffHandle);
+
+ /* Generate relocation information and replace all label references
+ * in the code with actual program section data offsets.
+ */
+
+ pass3(poffHandle, poffProgHandle);
+
+ /* Fixed label references in the debug function information */
+
+ pass4(poffHandle);
+
+ /* Reset for next pass */
+
+ insn_ResetOpCodeRead(poffHandle);
+ insn_ResetTmpOpCodeWrite(poffProgHandle);
+
+ /* Finally, replace file header entry point with the I-space offset */
+
+ pass5(poffHandle);
+
+ /* Clean up after ourselves */
+
+ poffReleaseLabelReferences();
+}
+
+/**********************************************************************/