StackMap NFunctionSignature::generateStackMap() { StackMap map; // Add stack frame data for arguments. for (VariableList::const_iterator i = this->arguments.begin(); i != this->arguments.end(); i++) { map.insert(map.end(), StackPair((*i)->id.name, (*i)->type)); // FIXME: Check to make sure arguments do not clash with any // other argument declarations (hint: check the map to // see if it already has a match). } return map; }
AsmBlock* NDeclarations::compile(AsmGenerator& context) { AsmBlock* block = new AsmBlock(); // Import bootstrap data. *block << ".IMPORT _stack_caller_init" << std::endl; *block << ".IMPORT _stack_callee_return" << std::endl; *block << ".IMPORT _halt" << std::endl; *block << ".IMPORT _halt_debug" << std::endl; // Add file and line information. *block << this->getFileAndLineState(); // Tell the generator that we are the root. context.m_RootNode = this; // Create the global data frame. StackMap* map = new StackMap(); for (DeclarationList::iterator i = this->definitions.begin(); i != this->definitions.end(); i++) { if ((*i)->cType != "statement-declaration-variable") continue; map->insert(map->end(), StackPair(((NVariableDeclaration*)(*i))->id.name, ((NVariableDeclaration*)(*i))->type)); } context.m_GlobalFrame = new StackFrame(context, *map); // Output the global data storage area. *block << std::endl; *block << ":_DATA" << std::endl; for (DeclarationList::iterator i = this->definitions.begin(); i != this->definitions.end(); i++) { if ((*i)->cType != "statement-declaration-variable") continue; // Calculate size. unsigned int size = ((NVariableDeclaration*)(*i))->type.getWordSize(context); // We can't have types with 0 word storage in the global scope. if (size <= 0) throw new CompilerException(this->line, this->file, "Unable to store global variable with a type that has size of 0 words."); // Output zero'd data sections. *block << " DAT 0"; for (unsigned int b = 1; b < size; b++) *block << ", 0"; *block << std::endl; } *block << std::endl; // If the assembler supports sections... if (context.getAssembler().supportsSections) { // Output the block for initializing global data storage. *block << ".SECTION INIT" << std::endl; context.m_CurrentFrame = context.m_GlobalFrame; // So that the NVariableDeclaration compiles successfully. for (DeclarationList::iterator i = this->definitions.begin(); i != this->definitions.end(); i++) { if ((*i)->cType != "statement-declaration-variable") continue; // Compile initializer. AsmBlock* inner = (*i)->compile(context); *block << *inner; if (inner != NULL) delete inner; } // Output the code section. *block << ".SECTION CODE" << std::endl; } else { // Ensure we don't have any global variable initializers declared here. for (DeclarationList::iterator i = this->definitions.begin(); i != this->definitions.end(); i++) { if ((*i)->cType != "statement-declaration-variable") continue; if (((NVariableDeclaration*)(*i))->initExpr != NULL) throw new CompilerException(this->line, this->file, "Initializers not permitted on global variables for assemblers that don't support sections."); } } // Deal with the main setup. NFunctionDeclaration* main = (NFunctionDeclaration*)context.getFunction("main"); if (main != NULL) { // Get the stack table of main. StackFrame* frame = context.generateStackFrame(main, false); // Output assembly for calling main. *block << " SET X, " << frame->getParametersSize() << std::endl; *block << " SET Z, _halt" << std::endl; *block << " JSR _stack_caller_init" << std::endl; *block << " SET PC, cfunc_main" << std::endl; // Clean up frame. context.finishStackFrame(frame); } // Handle function definitions. for (DeclarationList::iterator i = this->definitions.begin(); i != this->definitions.end(); i++) { if ((*i)->cType == "statement-declaration-variable") continue; AsmBlock* inner = (*i)->compile(context); *block << *inner; if (inner != NULL) delete inner; } return block; }