Working towards functions.. We have parameters and function local types
This commit is contained in:
parent
0c148f6e0c
commit
389d4b47ff
|
@ -8,6 +8,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ARithmetic tokens are prefixed AR.
|
* ARithmetic tokens are prefixed AR.
|
||||||
|
@ -204,7 +205,7 @@ enum StorageScope {
|
||||||
SC_GLOBAL = 1, // Global Scope
|
SC_GLOBAL = 1, // Global Scope
|
||||||
//SC_CLASS, // Class-local definitions
|
//SC_CLASS, // Class-local definitions
|
||||||
//SC_STATIC, // Static storage definitions
|
//SC_STATIC, // Static storage definitions
|
||||||
//SC_PARAM, // Function parameters
|
SC_PARAM, // Function parameters
|
||||||
SC_LOCAL // Function-local scope.
|
SC_LOCAL // Function-local scope.
|
||||||
// There is no deeper scope than function.
|
// There is no deeper scope than function.
|
||||||
};
|
};
|
||||||
|
@ -327,6 +328,7 @@ int FindSymbol(char* Symbol);
|
||||||
|
|
||||||
int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length);
|
int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length);
|
||||||
|
|
||||||
|
void FreeLocals();
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* * * * C O N T R O L S T A T U S * * * *
|
* * * * C O N T R O L S T A T U S * * * *
|
||||||
|
@ -366,7 +368,7 @@ int AsLdLocalVar(int ID, int Operation);
|
||||||
int AsStrGlobalVar(int Register, int ID);
|
int AsStrGlobalVar(int Register, int ID);
|
||||||
int AsStrLocalVar(int Register, int ID);
|
int AsStrLocalVar(int Register, int ID);
|
||||||
|
|
||||||
int AsCalcOffset(int Type, int Param);
|
int AsCalcOffset(int Type);
|
||||||
void AsNewStackFrame();
|
void AsNewStackFrame();
|
||||||
|
|
||||||
int AsDeref(int Reg, int Type);
|
int AsDeref(int Reg, int Type);
|
||||||
|
@ -422,7 +424,7 @@ void AsFunctionEpilogue(int ID);
|
||||||
* * * * D E C L A R A T I O N * * * *
|
* * * * D E C L A R A T I O N * * * *
|
||||||
* * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
void BeginVariableDeclaration(int Type, int Scope);
|
void BeginVariableDeclaration(int Type, int Scope, bool isParameter);
|
||||||
struct ASTNode* ParseIdentifier(void);
|
struct ASTNode* ParseIdentifier(void);
|
||||||
|
|
||||||
struct ASTNode* IfStatement();
|
struct ASTNode* IfStatement();
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
/*
|
/*
|
||||||
* If the entry in UsedRegisters
|
* If the entry in UsedRegisters
|
||||||
* that correlates to the position of a register in Registers
|
* that correlates to the position of a register in Registers
|
||||||
* is 1
|
* is 1,
|
||||||
* then that register is classed as used -
|
* then that register is classed as used -
|
||||||
* it has useful data inside it.
|
* it has useful data inside it.
|
||||||
*
|
*
|
||||||
|
@ -19,9 +19,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int UsedRegisters[4];
|
static int UsedRegisters[4];
|
||||||
static char* Registers[4] = { "%r8", "%r9", "%r10", "%r11" };
|
/* The https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention
|
||||||
static char* DoubleRegisters[4] = { "%r8d", "%r9d", "%r10d", "%r11d" };
|
* calling convention on Windows requires that
|
||||||
static char* ByteRegisters[4] = { "%r8b", "%r9b", "%r10b", "%r11b" };
|
* the last 4 arguments are placed in registers
|
||||||
|
* rcx, rdx, r8 and r9.
|
||||||
|
* This order must be preserved, and they must be placed
|
||||||
|
* right to left.
|
||||||
|
*
|
||||||
|
* That is the reason for the weird arrangement here.
|
||||||
|
* The parameter registers are last, in reverse order.
|
||||||
|
*/
|
||||||
|
static char* Registers[10] = { "%rsi", "%rdi", "%r10", "%r11" , "%r12" , "%r13", "%r9" , "%r8", "%rdx", "%rcx" };
|
||||||
|
static char* DoubleRegisters[10] = { "%esi", "%edi", "%r10d", "%r11d", "%r12d", "%r13d", "%r9d", "%r8d", "%edx", "%ecx" };
|
||||||
|
static char* ByteRegisters[10] = { "%sil", "%dil", "%r10b", "%r11b", "%r12b", "%r13b", "%r9b", "%r8b", "%dl" , "%cl" };
|
||||||
|
|
||||||
static char* Comparisons[6] = { "sete", "setne", "setl", "setg", "setle", "setge" };
|
static char* Comparisons[6] = { "sete", "setne", "setl", "setg", "setle", "setge" };
|
||||||
static char* InvComparisons[6] = { "jne", "je", "jge", "jle", "jg", "jl"};
|
static char* InvComparisons[6] = { "jne", "je", "jge", "jle", "jg", "jl"};
|
||||||
|
@ -170,7 +180,7 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
||||||
|
|
||||||
case REF_IDENT:
|
case REF_IDENT:
|
||||||
if(Node->RVal || ParentOp == OP_DEREF) {
|
if(Node->RVal || ParentOp == OP_DEREF) {
|
||||||
if(Symbols[Node->Value.ID].Storage == SC_LOCAL)
|
if(Symbols[Node->Value.ID].Storage == SC_LOCAL || Symbols[Node->Value.ID].Storage == SC_PARAM)
|
||||||
return AsLdLocalVar(Node->Value.ID, Node->Operation);
|
return AsLdLocalVar(Node->Value.ID, Node->Operation);
|
||||||
else
|
else
|
||||||
return AsLdGlobalVar(Node->Value.ID, Node->Operation);
|
return AsLdGlobalVar(Node->Value.ID, Node->Operation);
|
||||||
|
@ -276,7 +286,7 @@ void AsNewStackFrame() {
|
||||||
LocalVarOffset = 0;
|
LocalVarOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsCalcOffset(int Type, int Param) {
|
int AsCalcOffset(int Type) {
|
||||||
LocalVarOffset += PrimitiveSize(Type) > 4 ? PrimitiveSize(Type) : 4;
|
LocalVarOffset += PrimitiveSize(Type) > 4 ? PrimitiveSize(Type) : 4;
|
||||||
return -LocalVarOffset;
|
return -LocalVarOffset;
|
||||||
}
|
}
|
||||||
|
@ -887,8 +897,10 @@ void AssemblerPreamble() {
|
||||||
|
|
||||||
void AsFunctionPreamble(int FunctionID) {
|
void AsFunctionPreamble(int FunctionID) {
|
||||||
char* Name = Symbols[FunctionID].Name;
|
char* Name = Symbols[FunctionID].Name;
|
||||||
|
int ParamOffset = 48, ParamReg = 9;
|
||||||
|
|
||||||
StackFrameOffset = (LocalVarOffset + 31) & ~31;
|
|
||||||
|
AsNewStackFrame();
|
||||||
|
|
||||||
fprintf(OutputFile,
|
fprintf(OutputFile,
|
||||||
"\t.text\n"
|
"\t.text\n"
|
||||||
|
@ -896,12 +908,42 @@ void AsFunctionPreamble(int FunctionID) {
|
||||||
"\t.def\t%s; .scl 2; .type 32; .endef\n"
|
"\t.def\t%s; .scl 2; .type 32; .endef\n"
|
||||||
"%s:\n"
|
"%s:\n"
|
||||||
"\tpushq\t%%rbp\n"
|
"\tpushq\t%%rbp\n"
|
||||||
"\tmovq\t%%rsp, %%rbp\n"
|
"\tmovq\t%%rsp, %%rbp\r\n",
|
||||||
"\taddq\t$%d, %%rsp\n", Name, Name, Name, -StackFrameOffset);
|
Name, Name, Name);
|
||||||
|
|
||||||
//PECOFF requires we call the global initialisers
|
//PECOFF requires we call the global initialisers
|
||||||
if(!strcmp(Name, "main"))
|
if(!strcmp(Name, "main"))
|
||||||
fprintf(OutputFile, "\tcall\t__main\n");
|
fprintf(OutputFile, "\tcall\t__main\n");
|
||||||
|
|
||||||
|
// Need to share this between two loops. Fun.
|
||||||
|
int LoopIndex;
|
||||||
|
|
||||||
|
// If we have parameters, move them to the last 4 registers
|
||||||
|
for(LoopIndex = SYMBOLS - 1; LoopIndex > CurrentLocal; LoopIndex--) {
|
||||||
|
if(Symbols[LoopIndex].Storage != SC_PARAM)
|
||||||
|
break;
|
||||||
|
if(LoopIndex < SYMBOLS - 4) // We only have 4 argument registers
|
||||||
|
break;
|
||||||
|
|
||||||
|
Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type);
|
||||||
|
AsStrLocalVar(ParamReg--, LoopIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have more parameters, move them to the stack
|
||||||
|
for(; LoopIndex > CurrentLocal; LoopIndex--) {
|
||||||
|
if(Symbols[LoopIndex].Storage == SC_PARAM) {
|
||||||
|
Symbols[LoopIndex].SinkOffset = ParamOffset;
|
||||||
|
ParamOffset += 8;
|
||||||
|
} else {
|
||||||
|
Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// With all the parameters on the stack, we can allocate the shadow space
|
||||||
|
StackFrameOffset = (LocalVarOffset + 31) & ~31;
|
||||||
|
fprintf(OutputFile,
|
||||||
|
"\taddq\t$%d, %%rsp\n", -StackFrameOffset);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsFunctionEpilogue(int FunctionID) {
|
void AsFunctionEpilogue(int FunctionID) {
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
int TypeSizes[9] = { 0, 1, 4, 8, 0, 8, 8, 8, 8}; // in BYTES
|
int TypeSizes[9] = { 0, 1, 4, 8, 0, 8, 8, 8, 8}; // in BYTES
|
||||||
|
|
||||||
char* TokenNames[] = {
|
char* TokenNames[] = {
|
||||||
|
"", // Push everything up by one
|
||||||
"End of file",
|
"End of file",
|
||||||
"Equivalency",
|
"Equivalency",
|
||||||
|
|
||||||
|
|
|
@ -390,7 +390,8 @@ struct ASTNode* CallFunction() {
|
||||||
|
|
||||||
struct ASTNode* ParseStatement(void) {
|
struct ASTNode* ParseStatement(void) {
|
||||||
int Type;
|
int Type;
|
||||||
|
|
||||||
|
printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentToken.type], CurrentToken.type);
|
||||||
switch(CurrentToken.type) {
|
switch(CurrentToken.type) {
|
||||||
case TY_CHAR:
|
case TY_CHAR:
|
||||||
case TY_LONG:
|
case TY_LONG:
|
||||||
|
@ -398,7 +399,8 @@ struct ASTNode* ParseStatement(void) {
|
||||||
printf("\t\tNew Variable: %s\n", CurrentIdentifier);
|
printf("\t\tNew Variable: %s\n", CurrentIdentifier);
|
||||||
Type = ParseOptionalPointer();
|
Type = ParseOptionalPointer();
|
||||||
VerifyToken(TY_IDENTIFIER, "ident");
|
VerifyToken(TY_IDENTIFIER, "ident");
|
||||||
BeginVariableDeclaration(Type, SC_LOCAL);
|
BeginVariableDeclaration(Type, SC_LOCAL, false);
|
||||||
|
VerifyToken(LI_SEMIC, ";"); // TODO: single line assignment?
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*case TY_IDENTIFIER:
|
/*case TY_IDENTIFIER:
|
||||||
|
@ -481,9 +483,10 @@ void ParseGlobals() {
|
||||||
Tree = ParseFunction(Type);
|
Tree = ParseFunction(Type);
|
||||||
printf("\nBeginning assembler creation of new function %s\n", Symbols[Tree->Value.ID].Name);
|
printf("\nBeginning assembler creation of new function %s\n", Symbols[Tree->Value.ID].Name);
|
||||||
AssembleTree(Tree, -1, 0);
|
AssembleTree(Tree, -1, 0);
|
||||||
|
FreeLocals();
|
||||||
} else {
|
} else {
|
||||||
printf("\tParsing global variable declaration\n");
|
printf("\tParsing global variable declaration\n");
|
||||||
BeginVariableDeclaration(Type, SC_GLOBAL);
|
BeginVariableDeclaration(Type, SC_GLOBAL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CurrentToken.type == LI_EOF)
|
if(CurrentToken.type == LI_EOF)
|
||||||
|
|
|
@ -6,8 +6,31 @@
|
||||||
|
|
||||||
#include <Defs.h>
|
#include <Defs.h>
|
||||||
#include <Data.h>
|
#include <Data.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
static int ReadParameters() {
|
||||||
|
int TokenType, ParamCount = 0;
|
||||||
|
|
||||||
|
while(CurrentToken.type != LI_RPARE) {
|
||||||
|
TokenType = ParseOptionalPointer();
|
||||||
|
VerifyToken(TY_IDENTIFIER, "identifier");
|
||||||
|
|
||||||
|
BeginVariableDeclaration(TokenType, SC_PARAM, true);
|
||||||
|
ParamCount++;
|
||||||
|
|
||||||
|
switch(CurrentToken.type) {
|
||||||
|
case LI_COM:
|
||||||
|
Tokenise(&CurrentToken);
|
||||||
|
break;
|
||||||
|
case LI_RPARE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DieDecimal("Unexpected token in parameter", CurrentToken.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParamCount;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handles the declaration of a type of a variable.
|
* Handles the declaration of a type of a variable.
|
||||||
|
@ -22,7 +45,7 @@
|
||||||
* //TODO: int i = 5;
|
* //TODO: int i = 5;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void BeginVariableDeclaration(int Type, int Scope) {
|
void BeginVariableDeclaration(int Type, int Scope, bool isParameter) {
|
||||||
int ID;
|
int ID;
|
||||||
printf("type: %s\n", TypeNames[Type]);
|
printf("type: %s\n", TypeNames[Type]);
|
||||||
|
|
||||||
|
@ -31,27 +54,34 @@ void BeginVariableDeclaration(int Type, int Scope) {
|
||||||
//Type = Type - 2;
|
//Type = Type - 2;
|
||||||
if(CurrentToken.type == LI_INT) {
|
if(CurrentToken.type == LI_INT) {
|
||||||
printf("Adding array %s that is %d x %s.\r\n", CurrentIdentifier, CurrentToken.value, TypeNames[Type]);
|
printf("Adding array %s that is %d x %s.\r\n", CurrentIdentifier, CurrentToken.value, TypeNames[Type]);
|
||||||
AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 0, CurrentToken.value);
|
if(Scope == SC_LOCAL)
|
||||||
|
Die("Local arrays are not supported");
|
||||||
|
else
|
||||||
|
AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 0, CurrentToken.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokenise(&CurrentToken);
|
Tokenise(&CurrentToken);
|
||||||
VerifyToken(LI_RBRAS, "]");
|
VerifyToken(LI_RBRAS, "]");
|
||||||
} else {
|
} else {
|
||||||
printf("Adding var %s that is a %s\r\n", CurrentIdentifier, TypeNames[Type]);
|
printf("Adding var %s that is a %s\r\n", CurrentIdentifier, TypeNames[Type]);
|
||||||
AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 0, 1);
|
if(Scope == SC_LOCAL) {
|
||||||
|
if(AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 0, 1) == -1)
|
||||||
|
Die("Illegal state: Identical locals in current function");
|
||||||
|
} else {
|
||||||
|
AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 0, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VerifyToken(LI_SEMIC, ";");
|
//VerifyToken(LI_SEMIC, ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ASTNode* ParseFunction(int Type) {
|
struct ASTNode* ParseFunction(int Type) {
|
||||||
struct ASTNode* Tree;
|
struct ASTNode* Tree;
|
||||||
struct ASTNode* FinalStatement;
|
struct ASTNode* FinalStatement;
|
||||||
int SymbolSlot, BreakLabel;
|
int SymbolSlot, BreakLabel, ParamCount;
|
||||||
|
|
||||||
printf("\nIdentified function %s of return type %s\n", CurrentIdentifier, TypeNames[Type]);
|
|
||||||
|
|
||||||
BreakLabel = NewLabel();
|
BreakLabel = NewLabel();
|
||||||
|
printf("\nIdentified function %s of return type %s, end label %d\n", CurrentIdentifier, TypeNames[Type], BreakLabel);
|
||||||
|
|
||||||
SymbolSlot = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 1);
|
SymbolSlot = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 1);
|
||||||
CurrentFunction = SymbolSlot;
|
CurrentFunction = SymbolSlot;
|
||||||
|
@ -59,6 +89,8 @@ struct ASTNode* ParseFunction(int Type) {
|
||||||
AsNewStackFrame();
|
AsNewStackFrame();
|
||||||
|
|
||||||
VerifyToken(LI_LPARE, "(");
|
VerifyToken(LI_LPARE, "(");
|
||||||
|
ParamCount = ReadParameters();
|
||||||
|
Symbols[SymbolSlot].Length = ParamCount;
|
||||||
VerifyToken(LI_RPARE, ")");
|
VerifyToken(LI_RPARE, ")");
|
||||||
|
|
||||||
Tree = ParseCompound();
|
Tree = ParseCompound();
|
||||||
|
|
|
@ -22,7 +22,7 @@ int FindSymbolImpl(char* Symbol, int Storage) {
|
||||||
: SYMBOLS /* Otherwise, start at the end and work backward */
|
: SYMBOLS /* Otherwise, start at the end and work backward */
|
||||||
);
|
);
|
||||||
Ind++) {
|
Ind++) {
|
||||||
|
if(Storage == SC_GLOBAL && Symbols[Ind].Storage == SC_PARAM) continue; // Skip searching globals for parameters.
|
||||||
if(*Symbol == *Symbols[Ind].Name && !strcmp(Symbol, Symbols[Ind].Name)) {
|
if(*Symbol == *Symbols[Ind].Name && !strcmp(Symbol, Symbols[Ind].Name)) {
|
||||||
printf("\t\tFound %s at %d\r\n", Symbol, Ind);
|
printf("\t\tFound %s at %d\r\n", Symbol, Ind);
|
||||||
return Ind;
|
return Ind;
|
||||||
|
@ -83,6 +83,15 @@ static int NewLocalSymbol() {
|
||||||
return Pos;
|
return Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the local counter on functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FreeLocals() {
|
||||||
|
CurrentLocal = SYMBOLS - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a symbol to the tables, and set all the metadata.
|
* Add a symbol to the tables, and set all the metadata.
|
||||||
* @param Name: The string representing the name of the symbol.
|
* @param Name: The string representing the name of the symbol.
|
||||||
|
@ -99,19 +108,27 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in
|
||||||
int TableSlot;
|
int TableSlot;
|
||||||
int SinkOffset = 0;
|
int SinkOffset = 0;
|
||||||
|
|
||||||
if((TableSlot = FindSymbolImpl(Name, Storage) != -1))
|
if((TableSlot = FindSymbolImpl(Name, Storage)) != -1)
|
||||||
return TableSlot;
|
return -1;
|
||||||
|
|
||||||
// Instaed of spliting this up into AddLocalSymbol and AddGlobalSymbol,
|
// Instaed of spliting this up into AddLocalSymbol and AddGlobalSymbol,
|
||||||
// we can use this switch to avoid duplicated code.
|
// we can use this switch to avoid duplicated code.
|
||||||
switch(Storage) {
|
switch(Storage) {
|
||||||
|
case SC_PARAM:
|
||||||
|
// Instead of special casing parameters, we can just add these to the symbol lists and be done with it.
|
||||||
|
printf("\tPreparing new parameter %s of type %s\r\n", Name, TypeNames[Type]);
|
||||||
|
TableSlot = AddSymbol(Name, Type, Structure, SC_GLOBAL, 88, 1);
|
||||||
|
Symbols[TableSlot].Storage = SC_PARAM; // Fix the parameter after running the global process
|
||||||
|
TableSlot = AddSymbol(Name, Type, Structure, SC_LOCAL, 88, 1);
|
||||||
|
Symbols[TableSlot].Storage = SC_PARAM; // Fix the parameter after running the local process
|
||||||
|
return TableSlot;
|
||||||
case SC_GLOBAL:
|
case SC_GLOBAL:
|
||||||
TableSlot = NewGlobalSymbol();
|
TableSlot = NewGlobalSymbol();
|
||||||
break;
|
break;
|
||||||
case SC_LOCAL:
|
case SC_LOCAL:
|
||||||
printf("\tCreating new local symbol %s\r\n", Name);
|
printf("\tCreating new local symbol %s\r\n", Name);
|
||||||
TableSlot = NewLocalSymbol();
|
TableSlot = NewLocalSymbol();
|
||||||
SinkOffset = AsCalcOffset(Type, 0);
|
SinkOffset = AsCalcOffset(Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,12 +138,13 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in
|
||||||
Symbols[TableSlot].Storage = Storage;
|
Symbols[TableSlot].Storage = Storage;
|
||||||
Symbols[TableSlot].Length = Length;
|
Symbols[TableSlot].Length = Length;
|
||||||
Symbols[TableSlot].SinkOffset = SinkOffset;
|
Symbols[TableSlot].SinkOffset = SinkOffset;
|
||||||
|
Symbols[TableSlot].EndLabel = EndLabel;
|
||||||
|
|
||||||
// NOTE: Generating global symbol names must happen AFTER the name and type are declared.
|
// NOTE: Generating global symbol names must happen AFTER the name and type are declared.
|
||||||
switch(Storage) {
|
switch(Storage) {
|
||||||
case SC_GLOBAL:
|
case SC_GLOBAL:
|
||||||
printf("\tCreating new global symbol %s into slot %d\r\n", Name, TableSlot);
|
printf("\tCreating new global symbol %s into slot %d\r\n", Name, TableSlot);
|
||||||
if(Structure != ST_FUNC) {
|
if(Structure != ST_FUNC && EndLabel != 88) { // Magic keyword so that we don't generate ASM globals for parameters
|
||||||
printf("\t\tGenerating data symbol.\r\n");
|
printf("\t\tGenerating data symbol.\r\n");
|
||||||
AsGlobalSymbol(TableSlot);
|
AsGlobalSymbol(TableSlot);
|
||||||
}
|
}
|
||||||
|
|
17
tests/arguments
Normal file
17
tests/arguments
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
i32 :: twoparams(int a, i32 b) {
|
||||||
|
int c;
|
||||||
|
int d;
|
||||||
|
int e;
|
||||||
|
c = 3;
|
||||||
|
d = 4;
|
||||||
|
e = 5;
|
||||||
|
PrintInteger(a); PrintInteger(b); PrintInteger(c); PrintInteger(d); PrintInteger(e);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int eightparams(int a, int b, int c, int d, int e, int f, int g, int h) {
|
||||||
|
PrintInteger(a); PrintInteger(b); PrintInteger(c);
|
||||||
|
PrintInteger(d); PrintInteger(e); PrintInteger(f);
|
||||||
|
PrintInteger(g); PrintInteger(h);
|
||||||
|
return (0);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user