public void Emit(CompilationContext context) { context.EmitComment(";Multiplicative expression"); ((ICodeEmitter)Tokens[0]).Emit(context); var t1ExpressionType = ((IHasType)Tokens[0]).GetExpressionType(context); if (Tokens.Count > 1) { TypeChecking.CheckExpressionTypeIsNumeric(t1ExpressionType); } for (int i = 1; i < Tokens.Count; i += 2) { ((ICodeEmitter)Tokens[i + 1]).Emit(context); var t2ExpressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context); TypeChecking.CheckExpressionTypeIsNumeric(t2ExpressionType); TypeChecking.CheckExpressionTypesMatch(t1ExpressionType, t2ExpressionType); t1ExpressionType = t2ExpressionType; string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value; context.EmitInstruction(new IRPop() { To = "ebx" }); context.EmitInstruction(new IRPop() { To = "eax" }); switch (op) { case "*": context.EmitInstruction(new IRMult() { Left = "eax", Right = "ebx", To = "ecx" }); break; case "/": context.EmitInstruction(new IRDiv() { Left = "eax", Right = "ebx", To = "ecx" }); break; } context.EmitInstruction(new IRPushRegister() { From = "ecx" }); } }
public void Emit(CompilationContext context) { context.EmitComment(";Boolean expression"); ((ICodeEmitter)Tokens[0]).Emit(context); var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context); if (Tokens.Count > 1) { TypeChecking.CheckExpressionTypeIsBoolean(expressionType); } for (int i = 1; i < Tokens.Count; i += 2) { string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value; ((ICodeEmitter)Tokens[i + 1]).Emit(context); expressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context); TypeChecking.CheckExpressionTypeIsBoolean(expressionType); context.EmitInstruction(new IRPop() { To = "ebx" }); context.EmitInstruction(new IRPop() { To = "eax" }); var trueLabel = new LabelAddressValue(context.CreateNewLabel()); switch (op) { case "&&": context.EmitInstruction(new IRAnd() { Left = "eax", Right = "ebx", To = "ecx" }); context.EmitInstruction(new IRCompareImmediate() { Left = "ecx", Right = new ImmediateValue(0) }); context.EmitInstruction(new IRJumpNE() { Address = trueLabel }); break; case "||": context.EmitInstruction(new IROr() { Left = "eax", Right = "ebx", To = "ecx" }); context.EmitInstruction(new IRCompareImmediate() { Left = "ecx", Right = new ImmediateValue(0) }); context.EmitInstruction(new IRJumpNE() { Address = trueLabel }); break; } var skipTrueLabel = new LabelAddressValue(context.CreateNewLabel()); context.EmitInstruction(new IRPushImmediate() { Value = new ImmediateValue(0) }); context.EmitInstruction(new IRJumpImmediate() { Address = skipTrueLabel }); context.EmitLabel(trueLabel.Value); context.EmitInstruction(new IRPushImmediate() { Value = new ImmediateValue(1) }); context.EmitLabel(skipTrueLabel.Value); } }
public override void CaseADelegateInvokeExp(ADelegateInvokeExp node) { //Build a list of the possible methods AASourceFile currentFile = Util.GetAncestor <AASourceFile>(node); List <AMethodDecl> methods = new List <AMethodDecl>(); ANamedType type = (ANamedType)finalTrans.data.ExpTypes[node.GetReceiver()]; AMethodDecl delegateMethod = finalTrans.data.DelegateTypeLinks[type]; foreach (KeyValuePair <ADelegateExp, AMethodDecl> delegateCreationPair in finalTrans.data.DelegateCreationMethod) { if (TypeChecking.Assignable(delegateCreationPair.Key.GetType(), type)) { if (!methods.Contains(delegateCreationPair.Value)) { methods.Add(delegateCreationPair.Value); } } } MoveMethodDeclsOut mover; if (methods.Count == 0) { //Can only remove it if the return value is unused if (!(node.Parent() is AExpStm)) { finalTrans.errors.Add(new ErrorCollection.Error(node.GetToken(), currentFile, "No possible methods found for delegate invoke.")); throw new ParserException(node.GetToken(), "Delegates.OutADelegateInvokeExp"); } mover = new MoveMethodDeclsOut("delegateVar", finalTrans.data); foreach (Node arg in node.GetArgs()) { arg.Apply(mover); } node.Parent().Parent().RemoveChild(node.Parent()); foreach (PStm stm in mover.NewStatements) { stm.Apply(this); } return; } if (methods.Count == 1) { ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList()); while (node.GetArgs().Count > 0) { invoke.GetArgs().Add(node.GetArgs()[0]); } //If we have a struct method, add the pointer from the delegate if (finalTrans.data.StructMethods.Any(str => str.Value.Contains(methods[0]))) { AStructDecl targetStr = finalTrans.data.StructMethods.First(str => str.Value.Contains(methods[0])).Key; AMethodDecl getPointerDecl = GetPointerMethod(targetStr.GetDimention() != null); ASimpleInvokeExp getPointerInvoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList() { node.GetReceiver() }); invoke.GetArgs().Add(getPointerInvoke); finalTrans.data.SimpleMethodLinks[getPointerInvoke] = getPointerDecl; finalTrans.data.ExpTypes[getPointerInvoke] = getPointerDecl.GetReturnType(); } finalTrans.data.SimpleMethodLinks[invoke] = methods[0]; finalTrans.data.ExpTypes[invoke] = methods[0].GetReturnType(); node.ReplaceBy(invoke); return; } //Multiple methods. Make /* * <Methods moved out from reciever> * string delegate = GetMethodPart(<reciever>); * if (delegate == "...") * { * Foo(...); * } * else if (delegate == "...") * { * Bar(..., GetPointerPart(<reciever>); * } * else if(...) * ... * else * { * UIDisplayMessage(PlayerGroupAll(), c_messageAreaDebug, StringToText("[<file>:<line>]: No methods matched delegate.")); * int i = 1/0; * return; * } * */ AABlock block = new AABlock(new ArrayList(), new TRBrace("}")); mover = new MoveMethodDeclsOut("delegateVar", finalTrans.data); node.GetReceiver().Apply(mover); AMethodDecl methodPartMethod = GetMethodMethod(); ASimpleInvokeExp methodPartInvoke = new ASimpleInvokeExp(new TIdentifier("GetMethodPart"), new ArrayList() { Util.MakeClone(node.GetReceiver(), finalTrans.data) }); finalTrans.data.SimpleMethodLinks[methodPartInvoke] = methodPartMethod; finalTrans.data.ExpTypes[methodPartInvoke] = methodPartMethod.GetReturnType(); AALocalDecl methodPartDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("string"), null), new TIdentifier("methodPart"), methodPartInvoke); block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), methodPartDecl)); //If the invoke's return value is used, get the lvalue PLvalue leftSide; if (node.Parent() is AALocalDecl) { leftSide = new ALocalLvalue(new TIdentifier("renameMe")); finalTrans.data.LocalLinks[(ALocalLvalue)leftSide] = (AALocalDecl)node.Parent(); finalTrans.data.LvalueTypes[leftSide] = new ANamedType(new TIdentifier("string"), null); PStm pStm = Util.GetAncestor <PStm>(node); AABlock pBlock = (AABlock)pStm.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm) + 1, new ABlockStm(new TLBrace("{"), block)); node.Parent().RemoveChild(node); } else if (node.Parent() is AAssignmentExp) { AAssignmentExp assignExp = (AAssignmentExp)node.Parent(); leftSide = assignExp.GetLvalue(); leftSide.Apply(mover); PStm pStm = Util.GetAncestor <PStm>(node); pStm.ReplaceBy(new ABlockStm(new TLBrace("{"), block)); } else if (node.Parent() is AExpStm) { //No assignments needed leftSide = null; node.Parent().ReplaceBy(new ABlockStm(new TLBrace("{"), block)); } else { //Create a new local AALocalDecl leftSideDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(delegateMethod.GetReturnType(), finalTrans.data), new TIdentifier("delegateVar"), null); ALocalLvalue leftSideLink = new ALocalLvalue(new TIdentifier("delegateVar")); ALvalueExp leftSideLinkExp = new ALvalueExp(leftSideLink); PStm pStm = Util.GetAncestor <PStm>(node); AABlock pBlock = (AABlock)pStm.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), new ABlockStm(new TLBrace("{"), block)); node.ReplaceBy(leftSideLinkExp); finalTrans.data.LocalLinks[leftSideLink] = leftSideDecl; finalTrans.data.LvalueTypes[leftSideLink] = finalTrans.data.ExpTypes[leftSideLinkExp] = leftSideDecl.GetType(); leftSide = leftSideLink; block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), leftSideDecl)); } ABlockStm elseBranch; //Make final else branch /* { * UIDisplayMessage(PlayerGroupAll(), c_messageAreaDebug, StringToText("<file>[<line>, <pos>]: No methods matched delegate.")); * IntToString(1/0); * return; * } */ { AABlock innerBlock = new AABlock(new ArrayList(), new TRBrace("}")); ASimpleInvokeExp playerGroupInvoke = new ASimpleInvokeExp(new TIdentifier("PlayerGroupAll"), new ArrayList()); AFieldLvalue messageAreaLink = new AFieldLvalue(new TIdentifier("c_messageAreaDebug")); ALvalueExp messageAreaLinkExp = new ALvalueExp(messageAreaLink); AStringConstExp stringConst = new AStringConstExp( new TStringLiteral("\"" + currentFile.GetName().Text.Replace('\\', '/') + "[" + node.GetToken().Line + ", " + node.GetToken().Pos + "]: Got a null delegate.\"")); ASimpleInvokeExp stringToTextInvoke = new ASimpleInvokeExp(new TIdentifier("StringToText"), new ArrayList() { stringConst }); ASimpleInvokeExp displayMessageInvoke = new ASimpleInvokeExp(new TIdentifier("UIDisplayMessage"), new ArrayList() { playerGroupInvoke, messageAreaLinkExp, stringToTextInvoke }); AIntConstExp intConst1 = new AIntConstExp(new TIntegerLiteral("1")); AIntConstExp intConst2 = new AIntConstExp(new TIntegerLiteral("0")); ABinopExp binop = new ABinopExp(intConst1, new ADivideBinop(new TDiv("/")), intConst2); ASimpleInvokeExp intToStringInvoke = new ASimpleInvokeExp(new TIdentifier("IntToString"), new ArrayList() { binop }); innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), displayMessageInvoke)); innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), intToStringInvoke)); //innerBlock.GetStatements().Add(new AVoidReturnStm(new TReturn("return"))); elseBranch = new ABlockStm(new TLBrace("{"), innerBlock); finalTrans.data.SimpleMethodLinks[playerGroupInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == playerGroupInvoke.GetName().Text); finalTrans.data.SimpleMethodLinks[stringToTextInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == stringToTextInvoke.GetName().Text); finalTrans.data.SimpleMethodLinks[displayMessageInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == displayMessageInvoke.GetName().Text); finalTrans.data.SimpleMethodLinks[intToStringInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == intToStringInvoke.GetName().Text); finalTrans.data.FieldLinks[messageAreaLink] = finalTrans.data.Libraries.Fields.First(m => m.GetName().Text == messageAreaLink.GetName().Text); finalTrans.data.ExpTypes[playerGroupInvoke] = finalTrans.data.SimpleMethodLinks[playerGroupInvoke].GetReturnType(); finalTrans.data.LvalueTypes[messageAreaLink] = finalTrans.data.ExpTypes[messageAreaLinkExp] = finalTrans.data.FieldLinks[messageAreaLink].GetType(); finalTrans.data.ExpTypes[stringToTextInvoke] = finalTrans.data.SimpleMethodLinks[stringToTextInvoke].GetReturnType(); finalTrans.data.ExpTypes[stringConst] = finalTrans.data.ExpTypes[intToStringInvoke] = new ANamedType(new TIdentifier("string"), null); finalTrans.data.ExpTypes[displayMessageInvoke] = new AVoidType(); finalTrans.data.ExpTypes[intConst1] = finalTrans.data.ExpTypes[intConst2] = finalTrans.data.ExpTypes[binop] = new ANamedType(new TIdentifier("int"), null); } foreach (AMethodDecl method in methods) { /* * if (delegate == "...") * { * Foo(...); * } * else if (delegate == "...") * { * Bar(..., GetPointerPart(<reciever>); * } * else if(...) * ... */ AABlock innerBlock = new AABlock(new ArrayList(), new TRBrace("}")); ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier(method.GetName().Text), new ArrayList()); for (int i = 0; i < node.GetArgs().Count; i++) { PExp arg = (PExp)node.GetArgs()[i]; invoke.GetArgs().Add(Util.MakeClone(arg, finalTrans.data)); } //If we have a struct method, add the pointer from the delegate if (finalTrans.data.StructMethods.Any(str => str.Value.Contains(method))) { AStructDecl targetStr = finalTrans.data.StructMethods.First(str => str.Value.Contains(method)).Key; AMethodDecl getPointerDecl = GetPointerMethod(targetStr.GetDimention() != null); ASimpleInvokeExp getPointerInvoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList() { Util.MakeClone(node.GetReceiver(), data) }); invoke.GetArgs().Add(getPointerInvoke); finalTrans.data.SimpleMethodLinks[getPointerInvoke] = getPointerDecl; finalTrans.data.ExpTypes[getPointerInvoke] = getPointerDecl.GetReturnType(); } finalTrans.data.SimpleMethodLinks[invoke] = method; finalTrans.data.ExpTypes[invoke] = method.GetReturnType(); if (leftSide == null) { innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), invoke)); } else { AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), Util.MakeClone(leftSide, finalTrans.data), invoke); finalTrans.data.ExpTypes[assignment] = finalTrans.data.ExpTypes[invoke]; innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), assignment)); } ALocalLvalue methodPartLink = new ALocalLvalue(new TIdentifier("methodPart")); ALvalueExp methodPartLinkExp = new ALvalueExp(methodPartLink); AStringConstExp stringConst = new AStringConstExp(new TStringLiteral("\"" + GetName(method) + "\"")); finalTrans.data.LocalLinks[methodPartLink] = methodPartDecl; finalTrans.data.LvalueTypes[methodPartLink] = finalTrans.data.ExpTypes[methodPartLinkExp] = finalTrans.data.ExpTypes[stringConst] = new ANamedType(new TIdentifier("string"), null); ABinopExp binop = new ABinopExp(methodPartLinkExp, new AEqBinop(new TEq("==")), stringConst); finalTrans.data.ExpTypes[binop] = new ANamedType(new TIdentifier("bool"), null); AIfThenElseStm ifThenElse = new AIfThenElseStm(new TLParen("("), binop, new ABlockStm(new TLBrace("{"), innerBlock), elseBranch); elseBranch = new ABlockStm(new TLBrace("{"), new AABlock(new ArrayList() { ifThenElse }, new TRBrace("}"))); } block.GetStatements().Add(elseBranch); }
public void Emit(CompilationContext context) { context.EmitComment(";Return statement"); context.ReportReturnStatement(); var returnExpressionType = new ExpressionType() { BaseType = new TypeDef() { Name = "void", Size = 0 } }; if (Tokens.Count > 1) { returnExpressionType = ((IHasType)Tokens[1]).GetExpressionType(context); ((ICodeEmitter)Tokens[1]).Emit(context); //(Caller saves registers) if (returnExpressionType.GetSize() > 4) { //Return value gets placed space allocated in caller's stack throw new Exception("Large return values not supported"); } else { //Return value from function goes in eax context.EmitInstruction(new IRPop() { To = "eax" }); } } int localVarsSize = context.GetFunctionLocalVarSize(); //Reclaim local variables from stack space context.EmitInstruction(new IRMoveImmediate() { To = "ebx", Value = new ImmediateValue(localVarsSize) }); context.EmitInstruction(new IRSub() { To = "sp", Left = "sp", Right = "ebx" }); TypeChecking.CheckExpressionTypesMatch(context.GetCurrentFunctionReturnExpressionType(), returnExpressionType); if (context.IsEntryPointFunction) { //DONT WANT THIS. HALT JUST STOPS CPU COMPLETELY NOW //At this point the return value of the function is still in eax and we simple halt execution //as the exe has run to completion //context.EmitInstruction(new IRHalt()); } else { //Pop return address off stack and jump context.EmitInstruction(new IRRet()); } }
public void Emit(CompilationContext context) { context.EmitComment(";Function call"); var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context); if (!(expressionType.BaseType is FunctionTypeDef)) { throw new Exception("Can't call expression type: " + expressionType + " as a function"); } FunctionTypeDef functionType = (FunctionTypeDef)expressionType.BaseType; ExpressionType returnType = functionType.ReturnType; //List<ExpressionType> parameterTypes = functionType.ArgumentTypes; if (returnType.GetSize() > 4) { //Make space for return value in caller stack //context.EmitInstruction(new IRMoveImmediate() { To = "eax", Value = new ImmediateValue(function.ReturnType.GetSize()) }); //context.EmitInstruction(new IRAdd() { Left = "sp", Right = "eax", To = "sp" }); throw new LargeReturnValuesNotSupportedException(); } //Push base pointer on stack context.EmitInstruction(new IRPushRegister() { From = "bp" }); //Save registers (TODO: Not actually needed until we have smarter allocation that uses registers instead of stack) //context.EmitInstruction(new IRPushRegister() { From = "eax" }); //context.EmitInstruction(new IRPushRegister() { From = "ebx" }); //context.EmitInstruction(new IRPushRegister() { From = "ecx" }); //context.EmitInstruction(new IRPushRegister() { From = "edx" }); int argumentCount = Tokens.Count - 1; int argumentsSize = 0; if (argumentCount != functionType.ArgumentTypes.Count) { throw new ArgumentCountMismatchException(Tokens[0].ToString(), functionType.ArgumentTypes.Count, argumentCount); } if (Tokens.Count > 1) { //Push arguments on stack in reverse order for (int i = Tokens.Count - 1; i > 0; i--) { var argExpressionType = ((IHasType)Tokens[i]).GetExpressionType(context); var paramExpressionType = functionType.ArgumentTypes[functionType.ArgumentTypes.Count - 1 - (Tokens.Count - 1 - i)]; TypeChecking.CheckExpressionTypesMatch(paramExpressionType, argExpressionType); //Push argument value on stack ((ICodeEmitter)Tokens[i]).Emit(context); argumentCount++; argumentsSize += argExpressionType.GetSize(); } } var returnLabel = new LabelAddressValue(context.CreateNewLabel()); //Address of function -> eax ((ICodeEmitter)Tokens[0]).Emit(context); context.EmitInstruction(new IRPop() { To = "eax" }); //Set base pointer to be the top of current function's stack which will be the bottom //of the called function's stack context.EmitInstruction(new IRMoveRegister() { From = "sp", To = "bp" }); //Push return address context.EmitInstruction(new IRPushImmediate() { Value = returnLabel }); //Jump to function context.EmitInstruction(new IRJumpRegister() { Address = "eax" }); //Resume here, reclaim space from arguments pushed on stack context.EmitLabel(returnLabel.Value); context.EmitInstruction(new IRMoveImmediate() { To = "ebx", Value = new ImmediateValue(argumentsSize) }); context.EmitInstruction(new IRSub() { To = "sp", Left = "sp", Right = "ebx" }); //Restore registers (TODO: Not actually needed until we have smarter allocation that uses registers instead of stack) //context.EmitInstruction(new IRPop() { To = "edx" }); //context.EmitInstruction(new IRPop() { To = "ecx" }); //context.EmitInstruction(new IRPop() { To = "ebx" }); //context.EmitInstruction(new IRPop() { To = "eax" }); //Reset base pointer context.EmitInstruction(new IRPop() { To = "bp" }); if (returnType.GetSize() > 4) { //Return value is already on stack throw new LargeReturnValuesNotSupportedException(); } else if (returnType.GetSize() > 0) { //Return value in eax, put on stack context.EmitInstruction(new IRPushRegister() { From = "eax" }); } }
public void Emit(CompilationContext context) { context.EmitComment(";Variable definition"); var type = ((IHasType)Tokens[0]).GetExpressionType(context); string variableName = ((IdentifierToken)Tokens[1]).Name; if (type.IsArray && type.ArrayLength == -1) { throw new MissingArraySizeSpecifierException(variableName); } context.AddVariableSymbol(variableName, type, IsStatic, IsExported, IsExtern); if (!IsStatic && !context.InFunctionScope()) { throw new Exception("Cannot define non static variable outside of function scope."); } if (Tokens.Count > 2) { var assignmentExpressionType = ((IHasType)Tokens[3]).GetExpressionType(context); var variable = context.GetVariable(variableName); if (variable.Type.GetSize() == 0) { throw new VoidAssignmentException("to"); } else if (assignmentExpressionType.GetSize() == 0) { throw new VoidAssignmentException("from"); } TypeChecking.CheckExpressionTypesMatch(variable.Type, assignmentExpressionType); //Special case for assignment of string literal to byte array: // Don't emit string constant normally (which would add it as a string constant in the data section), // instead copy the string to the memory occupied by tge byte array itself if (assignmentExpressionType.BaseType is StringLiteralTypeDef && variable.Type.IsArray) { string stringLiteral = ((StringLiteralTypeDef)assignmentExpressionType.BaseType).Value; if (assignmentExpressionType.ArrayLength > variable.Type.ArrayLength) { throw new Exception("The string '" + stringLiteral + "' is too large to be assigned by value to the left hand expression."); } //Put start address to copy string value to into eax if (variable.Address is StackAddressValue) { context.EmitInstruction(new IRMoveImmediate() { To = "ebx", Value = new ImmediateValue(variable.Address.Value) }); context.EmitInstruction(new IRAdd() { To = "ebx", Left = "bp", Right = "ebx" }); context.EmitInstruction(new IRPushRegister() { From = "ebx" }); } else { context.EmitInstruction(new IRPushImmediate() { Value = variable.Address }); } context.EmitInstruction(new IRPop() { To = "eax" }); for (int i = 0; i < assignmentExpressionType.ArrayLength; i++) { byte charValue = i < stringLiteral.Length ? (byte)stringLiteral[i] : (byte)0; //Put char value into ebx context.EmitInstruction(new IRMoveImmediate() { To = "ebx", Value = new ImmediateValue(charValue), OperandSize = 1 }); //Store char value into address [eax + char offset] context.EmitInstruction(new IRStoreRegisterPlusImmediate() { To = "eax", Offset = new ImmediateValue(i), From = "ebx", OperandSize = 1 }); } } else { if (assignmentExpressionType.GetSize() > 4) { //Memory copy //Dest address -> eax throw new Exception("TODO: Copy large values to stack variables"); //context.EmitInstruction(new IRMoveImmediate() { To = "eax", Value = variable.Address }); //STACK!!!! //Source address -> ebx //((IHasAddress)Tokens[3]).PushAddress(context); //context.EmitInstruction(new IRPop() { To = "ebx" }); //context.EmitInstruction(new IRMemCopy() { From = "ebx", To = "eax", Length = new ImmediateValue(assignmentExpressionType.GetSize()) }); } else { //Copy using register ((ICodeEmitter)Tokens[3]).Emit(context); context.EmitInstruction(new IRPop() { To = "eax" }); if (variable.Address is StackAddressValue) { context.EmitInstruction(new IRStoreRegisterPlusImmediate() { From = "eax", To = "bp", Offset = new ImmediateValue(variable.Address.Value), OperandSize = assignmentExpressionType.GetSize() }); } else { context.EmitInstruction(new IRStoreImmediate() { From = "eax", To = variable.Address, OperandSize = assignmentExpressionType.GetSize() }); } } } } }
public void Emit(CompilationContext context) { context.EmitComment(";Assignment"); var leftSideExpressionType = ((IHasType)Tokens[0]).GetExpressionType(context); var rightSideExpressionType = ((IHasType)Tokens[2]).GetExpressionType(context); if (leftSideExpressionType.IsArray) { throw new TypeMismatchException(new ExpressionType() { IsArray = true, BaseType = leftSideExpressionType.BaseType, ArrayLength = leftSideExpressionType.ArrayLength }, rightSideExpressionType); } if (leftSideExpressionType.GetSize() == 0) { throw new VoidAssignmentException("to"); } else if (rightSideExpressionType.GetSize() == 0) { throw new VoidAssignmentException("from"); } TypeChecking.CheckExpressionTypesMatch(leftSideExpressionType, rightSideExpressionType); //Special case for assignment of string literal to byte array: // Don't emit string constant normally (which would add it as a string constant in the data section), // instead copy the string to the memory occupied by tge byte array itself if (rightSideExpressionType.BaseType is StringLiteralTypeDef && leftSideExpressionType.IsArray) { string stringLiteral = ((StringLiteralTypeDef)rightSideExpressionType.BaseType).Value; if (rightSideExpressionType.ArrayLength > leftSideExpressionType.ArrayLength) { throw new Exception("The string '" + stringLiteral + "' is too large to be assigned by value to the left hand expression."); } //Put start address to copy string value to into eax ((IHasAddress)Tokens[0]).PushAddress(context); context.EmitInstruction(new IRPop() { To = "eax" }); for (int i = 0; i < leftSideExpressionType.ArrayLength; i++) { byte charValue = i < stringLiteral.Length ? (byte)stringLiteral[i] : (byte)0; //Put char value into ebx context.EmitInstruction(new IRMoveImmediate() { To = "ebx", Value = new ImmediateValue(charValue), OperandSize = 1 }); //Store char value into address [eax + char offset] context.EmitInstruction(new IRStoreRegisterPlusImmediate() { To = "eax", Offset = new ImmediateValue(i), From = "ebx", OperandSize = 1 }); } } else { //right hand side value -> stack ((ICodeEmitter)Tokens[2]).Emit(context); if (rightSideExpressionType.GetSize() > 4) { //[sp] -> [destination] //Dest address -> eax ((IHasAddress)Tokens[0]).PushAddress(context); context.EmitInstruction(new IRPop() { To = "eax" }); //sp -= size of value context.EmitInstruction(new IRMoveImmediate() { To = "ebx", Value = new ImmediateValue(rightSideExpressionType.GetSize()) }); context.EmitInstruction(new IRSub() { Left = "sp", Right = "ebx", To = "sp" }); context.EmitInstruction(new IRMemCopy() { From = "sp", To = "eax", Length = new ImmediateValue(rightSideExpressionType.GetSize()) }); } else { //store ebx -> [destination] ((IHasAddress)Tokens[0]).PushAddress(context); context.EmitInstruction(new IRPop() { To = "eax" }); //Store assign value in ebx context.EmitInstruction(new IRPop() { To = "ebx" }); context.EmitInstruction(new IRStoreRegister() { From = "ebx", To = "eax", OperandSize = rightSideExpressionType.GetSize() }); //MB! } } }
public void Emit(CompilationContext context) { context.EmitComment(";Bitwise expression"); ((ICodeEmitter)Tokens[0]).Emit(context); var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context); if (Tokens.Count > 1) { TypeChecking.CheckExpressionTypeIsNumeric(expressionType); } for (int i = 1; i < Tokens.Count; i += 2) { string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value; ((ICodeEmitter)Tokens[i + 1]).Emit(context); expressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context); TypeChecking.CheckExpressionTypeIsNumeric(expressionType); context.EmitInstruction(new IRPop() { To = "ebx" }); context.EmitInstruction(new IRPop() { To = "eax" }); switch (op) { case "&": context.EmitInstruction(new IRAnd() { Left = "eax", Right = "ebx", To = "ecx" }); break; case "|": context.EmitInstruction(new IROr() { Left = "eax", Right = "ebx", To = "ecx" }); break; case "^": context.EmitInstruction(new IRXOr() { Left = "eax", Right = "ebx", To = "ecx" }); break; } context.EmitInstruction(new IRPushRegister() { From = "ecx" }); } }
public void Emit(CompilationContext context) { context.EmitComment(";Equality expression"); ((ICodeEmitter)Tokens[0]).Emit(context); var t1ExpressionType = ((IHasType)Tokens[0]).GetExpressionType(context); for (int i = 1; i < Tokens.Count; i += 2) { string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value; ((ICodeEmitter)Tokens[i + 1]).Emit(context); var t2ExpressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context); TypeChecking.CheckExpressionTypesMatch(t1ExpressionType, t2ExpressionType); t1ExpressionType = t2ExpressionType; context.EmitInstruction(new IRPop() { To = "ebx" }); context.EmitInstruction(new IRPop() { To = "eax" }); context.EmitInstruction(new IRCompareRegister() { Left = "eax", Right = "ebx" }); var trueLabel = new LabelAddressValue(context.CreateNewLabel()); switch (op) { case "==": context.EmitInstruction(new IRJumpEQ() { Address = trueLabel }); break; case "!=": context.EmitInstruction(new IRJumpNE() { Address = trueLabel }); break; case ">": context.EmitInstruction(new IRJumpGT() { Address = trueLabel }); break; case "<": context.EmitInstruction(new IRJumpLT() { Address = trueLabel }); break; case ">=": context.EmitInstruction(new IRJumpGE() { Address = trueLabel }); break; case "<=": context.EmitInstruction(new IRJumpLE() { Address = trueLabel }); break; } var skipTrueLabel = new LabelAddressValue(context.CreateNewLabel()); context.EmitInstruction(new IRPushImmediate() { Value = new ImmediateValue(0) }); context.EmitInstruction(new IRJumpImmediate() { Address = skipTrueLabel }); context.EmitLabel(trueLabel.Value); context.EmitInstruction(new IRPushImmediate() { Value = new ImmediateValue(1) }); context.EmitLabel(skipTrueLabel.Value); } }