Add parsing for function calls

This commit is contained in:
Curle 2021-01-17 21:56:37 +00:00
parent 389d4b47ff
commit 813a6c7827
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
4 changed files with 80 additions and 16 deletions

View File

@ -304,7 +304,7 @@ void ParseGlobals();
struct ASTNode* ParseFunction(int Type); struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound(); struct ASTNode* ParseCompound();
struct ASTNode* GetExpressionList();
struct ASTNode* CallFunction(); struct ASTNode* CallFunction();
struct ASTNode* ReturnStatement(); struct ASTNode* ReturnStatement();
@ -409,6 +409,8 @@ void AsLabel(int Label);
int AsShl(int Register, int Val); int AsShl(int Register, int Val);
int AsReturn(int Register, int FuncID); int AsReturn(int Register, int FuncID);
int AsCallWrapper(struct ASTNode* Node);
void AsCopyArgs(int Register, int Position);
int AsCall(int Register, int FuncID); int AsCall(int Register, int FuncID);
int AsWhile(struct ASTNode* Node); int AsWhile(struct ASTNode* Node);

View File

@ -66,6 +66,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
DeallocateAllRegisters(); DeallocateAllRegisters();
return -1; return -1;
case OP_CALL:
return (AsCallWrapper(Node));
case OP_FUNC: case OP_FUNC:
AsFunctionPreamble(Node->Value.ID); AsFunctionPreamble(Node->Value.ID);
AssembleTree(Node->Left, -1, Node->Operation); AssembleTree(Node->Left, -1, Node->Operation);
@ -141,12 +144,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
return LeftVal; //AsWiden(LeftVal, Node->Left->ExprType, Node->ExprType); return LeftVal; //AsWiden(LeftVal, Node->Left->ExprType, Node->ExprType);
case OP_RET: case OP_RET:
printf("\tReturning from %s, %d\n", Symbols[Node->Value.ID].Name, Node->Value.ID);
AsReturn(LeftVal, CurrentFunction); AsReturn(LeftVal, CurrentFunction);
return -1; return -1;
case OP_CALL:
printf("\tReturning from %s, %d\n", Symbols[Node->Value.ID].Name, Node->Value.ID);
return AsCall(LeftVal, Node->Value.ID);
/* case OP_EQUAL: /* case OP_EQUAL:
return AsEqual(LeftVal, RightVal); return AsEqual(LeftVal, RightVal);
@ -739,18 +739,42 @@ void AsGlobalSymbol(int ID) {
} }
} }
int AsCall(int Register, int FuncID) { int AsCallWrapper(struct ASTNode* Node) {
struct ASTNode* CompositeTree = Node->Left;
int Register, Args = 0;
while(CompositeTree) {
Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation);
AsCopyArgs(Register, CompositeTree->Value.Size);
if(Args == 0) Args = CompositeTree->Value.Size;
DeallocateAllRegisters();
CompositeTree = CompositeTree->Left;
}
return AsCall(Node->Value.ID, Args);
}
void AsCopyArgs(int Register, int Position) {
if(Position > 4) { // Args above 4 go on the stack
fprintf(OutputFile, "\tpushq\t%s\n", Registers[Register]);
} else {
fprintf(OutputFile, "\tmovq\t%s, %s\n", Registers[Register], Registers[10 - Position]);
}
}
int AsCall(int FuncID, int Args) {
int OutRegister = RetrieveRegister(); int OutRegister = RetrieveRegister();
printf("\t\tCalling function %s with parameter %s\n", Symbols[FuncID].Name, Registers[Register]); printf("\t\tCalling function %s with %d parameters\n", Symbols[FuncID].Name, Args);
printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]); printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]);
fprintf(OutputFile, "\tmovq\t%s, %%rcx\n", Registers[Register]);
fprintf(OutputFile, "\tcall\t%s\n", Symbols[FuncID].Name); fprintf(OutputFile, "\tcall\t%s\n", Symbols[FuncID].Name);
if(Args > 4)
fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4));
fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]); fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]);
DeallocateRegister(Register);
return OutRegister; return OutRegister;
} }
@ -897,10 +921,9 @@ 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; int ParamOffset = 0, ParamReg = 9;
LocalVarOffset = 4; // Prepare parameters
AsNewStackFrame();
fprintf(OutputFile, fprintf(OutputFile,
"\t.text\n" "\t.text\n"
@ -932,7 +955,7 @@ void AsFunctionPreamble(int FunctionID) {
// If we have more parameters, move them to the stack // If we have more parameters, move them to the stack
for(; LoopIndex > CurrentLocal; LoopIndex--) { for(; LoopIndex > CurrentLocal; LoopIndex--) {
if(Symbols[LoopIndex].Storage == SC_PARAM) { if(Symbols[LoopIndex].Storage == SC_PARAM) {
Symbols[LoopIndex].SinkOffset = ParamOffset; Symbols[LoopIndex].SinkOffset = ParamOffset + 16;
ParamOffset += 8; ParamOffset += 8;
} else { } else {
Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type); Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type);
@ -940,7 +963,7 @@ void AsFunctionPreamble(int FunctionID) {
} }
// With all the parameters on the stack, we can allocate the shadow space // With all the parameters on the stack, we can allocate the shadow space
StackFrameOffset = (LocalVarOffset + 31) & ~31; StackFrameOffset = ((LocalVarOffset + 31) & ~31);
fprintf(OutputFile, fprintf(OutputFile,
"\taddq\t$%d, %%rsp\n", -StackFrameOffset); "\taddq\t$%d, %%rsp\n", -StackFrameOffset);

View File

@ -158,7 +158,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
NodeType = CurrentToken.type; NodeType = CurrentToken.type;
//printf("%d\r\n", CurrentToken.type); //printf("%d\r\n", CurrentToken.type);
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) { if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) {
//printf("Current token matches ; ) ]\r\n"); //printf("Current token matches ; ) ]\r\n");
LeftNode->RVal = 1; return LeftNode; LeftNode->RVal = 1; return LeftNode;
} }
@ -373,7 +373,7 @@ struct ASTNode* CallFunction() {
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
Tree = ParsePrecedenceASTNode(0); Tree = GetExpressionList();
Tree = ConstructASTBranch(OP_CALL, Symbols[FuncID].Type, Tree, FuncID); Tree = ConstructASTBranch(OP_CALL, Symbols[FuncID].Type, Tree, FuncID);
@ -382,6 +382,29 @@ struct ASTNode* CallFunction() {
return Tree; return Tree;
} }
struct ASTNode* GetExpressionList() {
struct ASTNode* Tree = NULL, *Child = NULL;
int Count;
while(CurrentToken.type != LI_RPARE) {
Child = ParsePrecedenceASTNode(0);
Count++;
Tree = ConstructASTNode(OP_COMP, PTR_VOID, Tree, NULL, Child, Count);
switch(CurrentToken.type) {
case LI_COM:
Tokenise(&CurrentToken);
break;
case LI_RPARE:
break;
default:
Die("Unexpected token in argument list");
}
}
return Tree;
}
/* * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * *

16
tests/parameters Normal file
View File

@ -0,0 +1,16 @@
i32 :: params(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);
}
int :: add(i32 a, i32 b, i32 c) {
return (a + b + c);
}
i32 :: main() {
int Temp;
params(1, 2, 3, 5, 8, 13, 21, 34);
Temp = add(2, 3, 4);
PrintInteger(Temp);
return (0);
}