From 813a6c7827ce1fae331e0c65c8d15a8384f45d5f Mon Sep 17 00:00:00 2001 From: Curle Date: Sun, 17 Jan 2021 21:56:37 +0000 Subject: [PATCH] Add parsing for function calls --- include/Defs.h | 4 +++- src/Assembler.c | 49 +++++++++++++++++++++++++++++++++++------------- src/Parser.c | 27 ++++++++++++++++++++++++-- tests/parameters | 16 ++++++++++++++++ 4 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 tests/parameters diff --git a/include/Defs.h b/include/Defs.h index b433459..4e316d5 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -304,7 +304,7 @@ void ParseGlobals(); struct ASTNode* ParseFunction(int Type); struct ASTNode* ParseCompound(); - +struct ASTNode* GetExpressionList(); struct ASTNode* CallFunction(); struct ASTNode* ReturnStatement(); @@ -409,6 +409,8 @@ void AsLabel(int Label); int AsShl(int Register, int Val); int AsReturn(int Register, int FuncID); +int AsCallWrapper(struct ASTNode* Node); +void AsCopyArgs(int Register, int Position); int AsCall(int Register, int FuncID); int AsWhile(struct ASTNode* Node); diff --git a/src/Assembler.c b/src/Assembler.c index 7e503ab..3f97f62 100644 --- a/src/Assembler.c +++ b/src/Assembler.c @@ -66,6 +66,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { DeallocateAllRegisters(); return -1; + case OP_CALL: + return (AsCallWrapper(Node)); + case OP_FUNC: AsFunctionPreamble(Node->Value.ID); 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); case OP_RET: + printf("\tReturning from %s, %d\n", Symbols[Node->Value.ID].Name, Node->Value.ID); AsReturn(LeftVal, CurrentFunction); 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: 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(); - 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]); - fprintf(OutputFile, "\tmovq\t%s, %%rcx\n", Registers[Register]); 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]); - DeallocateRegister(Register); return OutRegister; } @@ -897,10 +921,9 @@ void AssemblerPreamble() { void AsFunctionPreamble(int FunctionID) { char* Name = Symbols[FunctionID].Name; - int ParamOffset = 48, ParamReg = 9; + int ParamOffset = 0, ParamReg = 9; - - AsNewStackFrame(); + LocalVarOffset = 4; // Prepare parameters fprintf(OutputFile, "\t.text\n" @@ -932,7 +955,7 @@ void AsFunctionPreamble(int FunctionID) { // If we have more parameters, move them to the stack for(; LoopIndex > CurrentLocal; LoopIndex--) { if(Symbols[LoopIndex].Storage == SC_PARAM) { - Symbols[LoopIndex].SinkOffset = ParamOffset; + Symbols[LoopIndex].SinkOffset = ParamOffset + 16; ParamOffset += 8; } else { 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 - StackFrameOffset = (LocalVarOffset + 31) & ~31; + StackFrameOffset = ((LocalVarOffset + 31) & ~31); fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", -StackFrameOffset); diff --git a/src/Parser.c b/src/Parser.c index e299d47..f26691b 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -158,7 +158,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) { NodeType = 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"); LeftNode->RVal = 1; return LeftNode; } @@ -373,7 +373,7 @@ struct ASTNode* CallFunction() { VerifyToken(LI_LPARE, "("); - Tree = ParsePrecedenceASTNode(0); + Tree = GetExpressionList(); Tree = ConstructASTBranch(OP_CALL, Symbols[FuncID].Type, Tree, FuncID); @@ -382,6 +382,29 @@ struct ASTNode* CallFunction() { 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; +} /* * * * * * * * * * * * * * * * * * * * * * diff --git a/tests/parameters b/tests/parameters new file mode 100644 index 0000000..698d360 --- /dev/null +++ b/tests/parameters @@ -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); +} \ No newline at end of file