Add parsing for function calls
This commit is contained in:
parent
389d4b47ff
commit
813a6c7827
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
27
src/Parser.c
27
src/Parser.c
|
@ -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
16
tests/parameters
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user