public static ExpressionTarget ParseFunctionInvocation(
            HlCompilation compilation,
            HlInvocationOp expr,
            int targetLength,
            string functionName,
            string jumpInstruction)
        {
            if (expr.ParameterList.Length != targetLength)
            {
                if (!(expr.MemberDefinition != null &&
                      (expr.MemberDefinition == expr.InstanceType.StaticConstructor ||
                       expr.MemberDefinition == expr.InstanceType.DynamicConstructor ||
                       expr.Instance == null)))
                {
                    EventManager <ErrorEvent> .SendEvent(
                        new FunctionArgumentMismatchEvent(
                            $"{functionName}: Invalid parameter Count. Expected {targetLength} got {expr.ParameterList.Length}"
                            )
                        );
                }
            }

            if (expr.Instance != null)
            {
                compilation.EmitterResult.Emit(
                    $"PUSH",
                    expr.Instance
                    );
            }

            foreach (HlExpression parameter in expr.ParameterList)
            {
                ExpressionTarget argVal = compilation.Parse(
                    parameter
                    );
                ExpressionTarget arg = argVal.MakeAddress(compilation);

                compilation.EmitterResult.Emit(
                    $"PUSH",
                    arg.ResultAddress
                    );

                compilation.ReleaseTempVar(arg.ResultAddress);

                compilation.ReleaseTempVar(argVal.ResultAddress);
            }

            compilation.EmitterResult.Emit(jumpInstruction, functionName);

            ExpressionTarget tempReturn = new ExpressionTarget(
                compilation.GetTempVarPop(),
                true,
                compilation.TypeSystem.GetType(
                    compilation.Root,
                    HLBaseTypeNames.s_UintTypeName
                    )
                );

            return(tempReturn);
        }
        public override ExpressionTarget ParseExpression(HlCompilation compilation, HlReturnOp expr)
        {
            if (expr.Right != null)
            {
                ExpressionTarget ptVal = compilation.Parse(
                    expr.Right
                    );
                ExpressionTarget pt = ptVal.
                                      MakeAddress(compilation);

                compilation.EmitterResult.Emit($"PUSH", pt.ResultAddress);

                compilation.ReleaseTempVar(pt.ResultAddress);
                compilation.ReleaseTempVar(ptVal.ResultAddress);
            }
            else
            {
                string v = SettingsManager.GetSettings <HlCompilerSettings>().OmitTempVarInit
                               ? compilation.GetTempVar()
                               : compilation.GetTempVar(0);
                compilation.EmitterResult.Emit($"PUSH", v);
                compilation.ReleaseTempVar(v);
            }

            compilation.EmitterResult.Emit("RET");

            return(new ExpressionTarget());
        }
Exemple #3
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlUnaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget targetVal = compilation.Parse(
                expr.Left
                );
            ExpressionTarget target = targetVal.MakeAddress(compilation);

            if (target.TypeDefinition.Name != HLBaseTypeNames.s_FloatTypeName)
            {
                EventManager <WarningEvent> .SendEvent(
                    new UnaryMinusExpressionInvalidEvent(
                        "Unary inversion is only possible with signed types and floats, performing this instruction on other types may yield undefined results."
                        )
                    );
            }

            if (outputTarget.ResultAddress == target.ResultAddress)
            {
                compilation.EmitterResult.Emit("INV.F", outputTarget.ResultAddress);

                return(outputTarget);
            }
            else
            {
                compilation.EmitterResult.Emit("INV.F", target.ResultAddress, outputTarget.ResultAddress);
                ExpressionTarget ret = target.CopyIfNotNull(compilation, outputTarget);
                compilation.ReleaseTempVar(target.ResultAddress);
                return(ret);
            }
        }
Exemple #4
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlArrayAccessorOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget tempPtrVar = compilation.Parse(expr.Left);

            ExpressionTarget tempPtr = new ExpressionTarget(
                SettingsManager.GetSettings <HlCompilerSettings>().OmitTempVarInit
                                                                ? compilation.GetTempVar()
                                                                : compilation.GetTempVar(0),
                true,
                tempPtrVar.TypeDefinition,
                true
                );

            ExpressionTarget pnVal = compilation.Parse(
                expr.ParameterList[0]
                );
            ExpressionTarget pn = pnVal.MakeAddress(compilation);

            if (tempPtrVar.TypeDefinition is ArrayTypeDefintion adef)
            {
                string tmpSName = compilation.GetTempVar(adef.ElementType.GetSize());
                compilation.EmitterResult.Emit($"MUL", pn.ResultAddress, tmpSName);
                compilation.ReleaseTempVar(tmpSName);
                compilation.EmitterResult.Emit($"LOAD", tempPtr.ResultAddress, tempPtrVar.ResultAddress);
            }
            else
            {
                string tmpSName = compilation.GetTempVar(tempPtrVar.TypeDefinition.GetSize());
                compilation.EmitterResult.Emit($"MUL", pn.ResultAddress, tmpSName);
                compilation.ReleaseTempVar(tmpSName);
                compilation.EmitterResult.Emit($"COPY", tempPtrVar.ResultAddress, tempPtr.ResultAddress);
            }

            compilation.EmitterResult.Emit($"ADD", tempPtr.ResultAddress, pn.ResultAddress);

            if (outputTarget.ResultAddress != null)
            {
                compilation.EmitterResult.Emit(
                    $"DREF",
                    tempPtr.ResultAddress,
                    outputTarget.ResultAddress
                    );

                compilation.ReleaseTempVar(tempPtr.ResultAddress);
                compilation.ReleaseTempVar(tempPtrVar.ResultAddress);
                compilation.ReleaseTempVar(pn.ResultAddress);
                compilation.ReleaseTempVar(pnVal.ResultAddress);

                return(outputTarget);
            }

            compilation.ReleaseTempVar(tempPtrVar.ResultAddress);
            compilation.ReleaseTempVar(pn.ResultAddress);
            compilation.ReleaseTempVar(pnVal.ResultAddress);

            return(tempPtr);
        }
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlUnaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget targetVal = compilation.Parse(
                expr.Left
                );
            ExpressionTarget target = targetVal.
                                      MakeAddress(compilation);

            //BNE target rTarget if_b0_fail
            //LOAD possibleTarget 0x1; True Value
            //.if_b0_fail
            string label = HlCompilation.GetUniqueName("bexpr_not");

            compilation.EmitterResult.Emit($"LOAD", outputTarget.ResultAddress, "1");
            compilation.EmitterResult.Emit($"BEZ", target.ResultAddress, label);
            compilation.EmitterResult.Emit($"LOAD", outputTarget.ResultAddress, "0");
            compilation.EmitterResult.Store($".{label} linker:hide");
            compilation.ReleaseTempVar(target.ResultAddress);
            compilation.ReleaseTempVar(targetVal.ResultAddress);

            return(outputTarget);
        }
Exemple #6
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlBinaryOp expr)
        {
            ExpressionTarget target = compilation.Parse(expr.Left);

            ExpressionTarget rTargetVal = compilation.Parse(
                expr.Right
                );
            ExpressionTarget rTarget = rTargetVal.MakeAddress(compilation);

            string instrKey =
                target.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName ||
                rTarget.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName
                    ? InstructionKey + ".F"
                    : InstructionKey;

            compilation.EmitterResult.Emit(
                instrKey,
                target.ResultAddress,
                rTarget.ResultAddress
                );

            compilation.ReleaseTempVar(rTarget.ResultAddress);
            compilation.ReleaseTempVar(rTargetVal.ResultAddress);

            return(target);
        }
Exemple #7
0
        public override ExpressionTarget ParseExpression(HlCompilation compilation, HlForOp expr)
        {
            string startLabel = HlCompilation.GetUniqueName("for_start");
            string condLabel  = HlCompilation.GetUniqueName("for_eval_condition");
            string endLabel   = HlCompilation.GetUniqueName("for_end");

            HlCompilation subFor = new HlCompilation(compilation, HlCompilation.GetUniqueName("for"));

            subFor.EmitterResult.Store(
                $".{startLabel} linker:hide"
                );                       //Unused, makes clear where the for compiler started emitting code.

            ExpressionTarget targetVal = subFor.Parse(expr.VDecl);
            ExpressionTarget target    = targetVal.MakeAddress(subFor); //Declare Variable(left)

            subFor.EmitterResult.Store($".{condLabel} linker:hide");    //Label to jumpto

            ExpressionTarget condVal = subFor.Parse(expr.Condition);    //Check Condition
            ExpressionTarget cond    = condVal.MakeAddress(subFor);     //Check Condition

            subFor.EmitterResult.Emit(
                $"BEZ",
                cond.ResultAddress,
                endLabel
                );                      //Check if Expression "Equal to Zero" => jump to end if it is

            foreach (HlExpression hlExpression in expr.ExprBody)
            {
                subFor.ReleaseTempVar(
                    subFor.Parse(hlExpression).
                    ResultAddress
                    );                  //Parse block and clean up any temp variables that were emitted.
            }

            subFor.ReleaseTempVar(subFor.Parse(expr.VInc).ResultAddress); //Compute Increment Expression

            subFor.EmitterResult.Emit($"JMP", condLabel);                 //Jump back up if we executed the body.

            subFor.EmitterResult.Store(
                $".{endLabel} linker:hide"
                );                       //End label that we jump to if we exit the loop

            subFor.ReleaseTempVar(target.ResultAddress);
            subFor.ReleaseTempVar(targetVal.ResultAddress);
            subFor.ReleaseTempVar(cond.ResultAddress);
            subFor.ReleaseTempVar(condVal.ResultAddress);

            compilation.EmitterResult.Store(subFor.EmitVariables(false));
            compilation.EmitterResult.Store(subFor.EmitterResult.Get());

            return(new ExpressionTarget());
        }
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlBinaryOp expr)
        {
            ExpressionTarget target = compilation.Parse(expr.Left);

            ExpressionTarget rTarget = compilation.Parse(
                expr.Right
                );

            if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeReduceExpressions&&
                IsReducable(rTarget))
            {
                uint   amount = GetPowLevel(rTarget.StaticParse());
                string tmp    = compilation.GetTempVarLoad(amount.ToString());

                ExpressionTarget taddr = target.MakeAddress(compilation);
                compilation.EmitterResult.Emit(
                    "SHR",
                    taddr.ResultAddress,
                    tmp
                    );

                compilation.ReleaseTempVar(tmp);
                compilation.ReleaseTempVar(taddr.ResultAddress);

                return(target);
            }

            string rtOrig = rTarget.ResultAddress;

            rTarget = rTarget.MakeAddress(compilation);

            string instrKey =
                target.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName ||
                rTarget.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName
                    ? InstructionKey + ".F"
                    : InstructionKey;

            compilation.EmitterResult.Emit(
                instrKey,
                target.ResultAddress,
                rTarget.ResultAddress
                );

            compilation.ReleaseTempVar(rTarget.ResultAddress);

            compilation.ReleaseTempVar(rtOrig);

            return(target);
        }
        public override ExpressionTarget ParseExpression(HlCompilation compilation, HlWhileOp expr)
        {
            string startLabel = HlCompilation.GetUniqueName("while_start");
            string endLabel   = HlCompilation.GetUniqueName("while_end");

            HlCompilation whileComp = new HlCompilation(compilation, HlCompilation.GetUniqueName("while"));

            whileComp.EmitterResult.Store($".{startLabel} linker:hide");
            ExpressionTarget targetVal = whileComp.Parse(expr.Condition);

            if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeWhileConditionExpressions&&
                !targetVal.IsAddress)
            {
                if (targetVal.StaticParse() != 0)

                //If True we parse body without check and directly jump to condition
                //If False we omit the whole loop entirely
                {
                    ParseBody(whileComp, expr, startLabel, endLabel);
                }

                compilation.EmitterResult.Store(whileComp.EmitVariables(false));
                compilation.EmitterResult.Store(whileComp.EmitterResult.Get());

                return(new ExpressionTarget());
            }

            ExpressionTarget target = targetVal.MakeAddress(whileComp);   //Make sure we have an address and not a static value

            whileComp.EmitterResult.Emit($"BEZ", target.ResultAddress, endLabel);

            ParseBody(whileComp, expr, startLabel, endLabel);

            whileComp.ReleaseTempVar(target.ResultAddress);
            whileComp.ReleaseTempVar(targetVal.ResultAddress);

            compilation.EmitterResult.Store(whileComp.EmitVariables(false));
            compilation.EmitterResult.Store(whileComp.EmitterResult.Get());

            //.while_start
            //LOAD tmp_condition_var 0x00
            //<PARSE CONDITION EXPR HERE>
            //BEZ tmp_condition_var while_end
            //<PARSE BLOCK HERE>
            //JMP while_start
            //.while_end
            return(new ExpressionTarget());
        }
Exemple #10
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlBinaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget target = compilation.Parse(expr.Left);

            ExpressionTarget rTargetVal = compilation.Parse(
                expr.Left
                );
            ExpressionTarget rTarget = rTargetVal.
                                       MakeAddress(compilation);


            if (target.ResultAddress == outputTarget.ResultAddress)
            {
                compilation.EmitterResult.Emit(
                    $"XOR",
                    target.ResultAddress,
                    rTarget.ResultAddress
                    );

                compilation.ReleaseTempVar(rTarget.ResultAddress);
                compilation.ReleaseTempVar(rTargetVal.ResultAddress);
            }
            else
            {
                compilation.EmitterResult.Emit(
                    $"XOR",
                    target.ResultAddress,
                    rTarget.ResultAddress,
                    outputTarget.ResultAddress
                    );

                compilation.ReleaseTempVar(rTarget.ResultAddress);
                compilation.ReleaseTempVar(target.ResultAddress);
                compilation.ReleaseTempVar(rTargetVal.ResultAddress);

                return(outputTarget);
            }

            return(target);
        }
Exemple #11
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlUnaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget targetVal = compilation.Parse(
                expr.Left
                );
            ExpressionTarget target = targetVal.
                                      MakeAddress(compilation);

            string tmp = compilation.GetTempVar(~( uint )0);

            compilation.EmitterResult.Emit($"XOR", target.ResultAddress, tmp);

            ExpressionTarget ret = target.CopyIfNotNull(compilation, outputTarget);

            compilation.ReleaseTempVar(tmp);
            compilation.ReleaseTempVar(target.ResultAddress);

            return(ret);
        }
Exemple #12
0
        public override ExpressionTarget ParseExpression(HlCompilation compilation, HlIfOp expr)
        {
            string endLabel    = HlCompilation.GetUniqueName("if_end");
            string elseLabel   = HlCompilation.GetUniqueName("if_else");
            string blockLabels = HlCompilation.GetUniqueName("if_b{0}");

            bool staticComputation = false;

            compilation.EmitterResult.Store("; Start IF");

            for (int i = 0; i < expr.ConditionMap.Count; i++)
            {
                string        thisLabel = string.Format(blockLabels, i);
                HlCompilation subIf     = new HlCompilation(compilation, HlCompilation.GetUniqueName(thisLabel));

                if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeIfConditionExpressions&&
                    expr.ConditionMap[i].Item1.IsStatic())
                {
                    ExpressionTarget t = subIf.Parse(
                        expr.ConditionMap[i].Item1
                        );

                    if (t.StaticParse() != 0)
                    {
                        staticComputation = true;

                        foreach (HlExpression hlExpression in expr.ConditionMap[i].Item2)
                        {
                            ExpressionTarget e = subIf.Parse(hlExpression);
                            compilation.ReleaseTempVar(e.ResultAddress);
                        }

                        compilation.EmitterResult.Store(subIf.EmitVariables(false));
                        compilation.EmitterResult.Store(subIf.EmitterResult.Get());

                        break;
                    }

                    if (i != 0)
                    {
                        subIf.EmitterResult.Store($".{thisLabel} linker:hide");
                    }

                    continue;
                }

                if (i != 0)
                {
                    subIf.EmitterResult.Store($".{thisLabel} linker:hide");
                }

                ExpressionTarget exprTargetVal = subIf.Parse(
                    expr.ConditionMap[i].Item1
                    );
                ExpressionTarget exprTarget = exprTargetVal.MakeAddress(subIf);

                string nextLabel;

                if (i < expr.ConditionMap.Count - 1)
                {
                    nextLabel = string.Format(blockLabels, i + 1);
                }
                else
                {
                    nextLabel = expr.ElseBranch != null ? elseLabel : endLabel;
                }

                subIf.EmitterResult.Emit($"BEZ", exprTarget.ResultAddress, nextLabel);

                foreach (HlExpression hlExpression in expr.ConditionMap[i].Item2)
                {
                    ExpressionTarget e = subIf.Parse(hlExpression);
                    compilation.ReleaseTempVar(e.ResultAddress);
                }

                subIf.EmitterResult.Emit($"JMP", endLabel);
                subIf.ReleaseTempVar(exprTarget.ResultAddress);
                subIf.ReleaseTempVar(exprTargetVal.ResultAddress);

                compilation.EmitterResult.Store(subIf.EmitVariables(false));
                compilation.EmitterResult.Store(subIf.EmitterResult.Get());
            }

            if (!staticComputation && expr.ElseBranch != null)
            {
                HlCompilation subIf = new HlCompilation(compilation, elseLabel);
                subIf.EmitterResult.Store($".{elseLabel} linker:hide");

                foreach (HlExpression hlExpression in expr.ElseBranch)
                {
                    ExpressionTarget e = subIf.Parse(hlExpression);
                    compilation.ReleaseTempVar(e.ResultAddress);
                }

                compilation.EmitterResult.Store(subIf.EmitVariables(false));
                compilation.EmitterResult.Store(subIf.EmitterResult.Get());
            }

            compilation.EmitterResult.Store($".{endLabel} linker:hide");

            return(new ExpressionTarget());
        }
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlBinaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget targetVal = compilation.Parse(
                expr.Left
                );

            ExpressionTarget rTargetVal = compilation.Parse(
                expr.Right
                );

            if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeConstExpressions&&
                !targetVal.IsAddress &&
                !rTargetVal.IsAddress)
            {
                return(new ExpressionTarget(
                           StaticEvaluate(targetVal, rTargetVal).ToString(),
                           false,
                           compilation.TypeSystem.GetType(
                               compilation.Root,
                               HLBaseTypeNames.s_UintTypeName
                               )
                           ));
            }

            ExpressionTarget target  = targetVal.MakeAddress(compilation);
            ExpressionTarget rTarget = rTargetVal.MakeAddress(compilation);

            if (target.IsPointer)
            {
                ExpressionTarget tmp = new ExpressionTarget(
                    compilation.GetTempVarDref(target.ResultAddress),
                    true,
                    compilation.TypeSystem.GetType(
                        compilation.Root,
                        HLBaseTypeNames.s_UintTypeName
                        )
                    );

                compilation.ReleaseTempVar(target.ResultAddress);
                compilation.ReleaseTempVar(targetVal.ResultAddress);
                target = tmp;
            }

            if (rTarget.IsPointer)
            {
                ExpressionTarget tmp = new ExpressionTarget(
                    compilation.GetTempVarDref(rTarget.ResultAddress),
                    true,
                    compilation.TypeSystem.GetType(
                        compilation.Root,
                        HLBaseTypeNames.s_UintTypeName
                        )
                    );

                compilation.ReleaseTempVar(rTarget.ResultAddress);
                compilation.ReleaseTempVar(rTargetVal.ResultAddress);
                rTarget = tmp;
            }

            //BNE target rTarget if_b0_fail
            //LOAD possibleTarget 0x1; True Value
            //.if_b0_fail
            string label = HlCompilation.GetUniqueName("rel_expr_comp");

            compilation.EmitterResult.Emit($"LOAD", outputTarget.ResultAddress, "1");

            compilation.EmitterResult.Store(
                $"{InstructionKey} {target.ResultAddress} {rTarget.ResultAddress} {label}"
                );

            compilation.EmitterResult.Emit($"LOAD", outputTarget.ResultAddress, "0");
            compilation.EmitterResult.Store($".{label} linker:hide");
            compilation.ReleaseTempVar(rTarget.ResultAddress);
            compilation.ReleaseTempVar(target.ResultAddress);
            compilation.ReleaseTempVar(targetVal.ResultAddress);
            compilation.ReleaseTempVar(rTargetVal.ResultAddress);

            return(outputTarget);
        }
Exemple #14
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlBinaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget targetVal  = compilation.Parse(expr.Left);
            ExpressionTarget rTargetVal = compilation.Parse(expr.Right);

            if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeConstExpressions&&
                !targetVal.IsAddress &&
                !rTargetVal.IsAddress)
            {
                return(ComputeStatic(compilation, targetVal, rTargetVal));
            }

            if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeConstExpressions)
            {
                uint             amount   = 0;
                ExpressionTarget baseExpr = default;

                if (IsReducable(targetVal))
                {
                    baseExpr = rTargetVal.MakeAddress(compilation);
                    amount   = GetPowLevel(targetVal.StaticParse());
                }
                else if (IsReducable(rTargetVal))
                {
                    baseExpr = targetVal.MakeAddress(compilation);
                    amount   = GetPowLevel(rTargetVal.StaticParse());
                }

                if (amount != 0)
                {
                    string tmp = compilation.GetTempVarLoad(amount.ToString());

                    compilation.EmitterResult.Emit(
                        "SHL",
                        baseExpr.ResultAddress,
                        tmp,
                        outputTarget.ResultAddress
                        );

                    compilation.ReleaseTempVar(tmp);
                    compilation.ReleaseTempVar(baseExpr.ResultAddress);
                    compilation.ReleaseTempVar(targetVal.ResultAddress);
                    compilation.ReleaseTempVar(rTargetVal.ResultAddress);

                    return(outputTarget);
                }
            }

            ExpressionTarget target  = targetVal.MakeAddress(compilation);
            ExpressionTarget rTarget = rTargetVal.MakeAddress(compilation);

            string instrKey =
                target.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName ||
                rTarget.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName
                    ? InstructionKey + ".F"
                    : InstructionKey;

            if (target.IsPointer)
            {
                ExpressionTarget et = new ExpressionTarget(
                    compilation.GetTempVarDref(target.ResultAddress),
                    true,
                    target.TypeDefinition
                    );

                compilation.EmitterResult.Emit(
                    instrKey,
                    et.ResultAddress,
                    rTarget.ResultAddress,
                    outputTarget.ResultAddress
                    );

                compilation.ReleaseTempVar(et.ResultAddress);
                compilation.ReleaseTempVar(rTarget.ResultAddress);
                compilation.ReleaseTempVar(target.ResultAddress);
                compilation.ReleaseTempVar(targetVal.ResultAddress);
                compilation.ReleaseTempVar(rTargetVal.ResultAddress);

                return(outputTarget);
            }

            compilation.EmitterResult.Emit(
                instrKey,
                target.ResultAddress,
                rTarget.ResultAddress,
                outputTarget.ResultAddress
                );

            compilation.ReleaseTempVar(rTarget.ResultAddress);
            compilation.ReleaseTempVar(target.ResultAddress);
            compilation.ReleaseTempVar(targetVal.ResultAddress);
            compilation.ReleaseTempVar(rTargetVal.ResultAddress);

            return(outputTarget);
        }
        public override ExpressionTarget ParseExpression(HlCompilation compilation, HlInvocationOp expr)
        {
            string target = expr.Left.ToString();

            if (m_CtFuncCollection.IsCompiletimeFunction(target))
            {
                return(m_CtFuncCollection.Compile(target, compilation, expr));
            }

            bool isInternalFunc = compilation.FunctionMap.Contains(target);

            IExternalData externalSymbol =
                compilation.ExternalSymbols.FirstOrDefault(
                    x => x.GetName() == target &&
                    x.DataType == ExternalDataType.Function
                    );

            //if (expr.Instance == null &&
            //    expr.MemberDefinition == null &&
            //    expr.InstanceType != null &&
            //    target == "new")
            //{
            //    ExpressionTarget instance = compilation.Parse(expr.ParameterList[0]);

            //    HlTypeDefinition tdef = expr.InstanceType;

            //    ExpressionTarget ret = new ExpressionTarget(
            //                                                instance.ResultAddress,
            //                                                true,
            //                                                tdef,
            //                                                true
            //                                               );

            //    if(SettingsManager.GetSettings<HlCompilerSettings>().ConstructorPrologMode == HlTypeConstructorPrologMode.Outline)
            //    WriteConstructorInvocationProlog(compilation, tdef, ret.ResultAddress);

            //    return ret;
            //}
            if (expr.Instance == null &&
                expr.InstanceType != null)
            {
                if (expr.MemberDefinition == expr.InstanceType.StaticConstructor)
                {
                    ExpressionTarget instance = compilation.Parse(expr.ParameterList[0]);

                    HlTypeDefinition tdef = expr.InstanceType;

                    ExpressionTarget ret = new ExpressionTarget(
                        instance.ResultAddress,
                        true,
                        tdef,
                        true
                        );

                    if (expr.WriteProlog &&
                        SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                        HlTypeConstructorPrologMode.Outline)
                    {
                        WriteConstructorInvocationProlog(compilation, tdef, ret.ResultAddress);
                    }

                    expr.Redirect(ret.ResultAddress, tdef, tdef.StaticConstructor, expr.WriteProlog);

                    ParseExpression(
                        compilation,
                        expr
                        );

                    return(ret);
                }
                else
                {
                    int l = (expr.MemberDefinition as HlFunctionDefinition).ParameterTypes.Length;

                    if (isInternalFunc)
                    {
                        compilation.FunctionMap.Get(target).SetUsed();
                    }
                    else
                    {
                        externalSymbol?.SetUsed();
                    }

                    return(ParseFunctionInvocation(compilation, expr, l, target, "JSR"));
                }
            }

            if (compilation.TypeSystem.HasType(compilation.Root, target))
            {
                string           var  = HlCompilation.GetUniqueName("static_alloc");
                HlTypeDefinition tdef = compilation.TypeSystem.GetType(compilation.Root, target);
                uint             size = tdef.GetSize();
                compilation.CreateVariable(var, size, tdef, VariableDataEmitFlags.None);
                string finalName = compilation.GetFinalName(var);

                ExpressionTarget ret = new ExpressionTarget(
                    compilation.GetTempVarLoad(finalName),
                    true,
                    tdef,
                    true
                    );

                if (SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                    HlTypeConstructorPrologMode.Outline)
                {
                    WriteConstructorInvocationProlog(compilation, tdef, ret.ResultAddress);
                }

                if (tdef.StaticConstructor != null)
                {
                    expr.Redirect(ret.ResultAddress, tdef, tdef.StaticConstructor);

                    ParseExpression(
                        compilation,
                        expr
                        );
                }

                return(ret);
            }

            if (expr.Instance != null &&
                expr.MemberDefinition is HlFunctionDefinition fdef)
            {
                if (fdef.IsVirtual || fdef.IsAbstract || fdef.IsOverride)
                {
                    uint i = expr.InstanceType.GetOffset(fdef.Name);

                    string init = i.ToString();
                    string tmp  = compilation.GetTempVarLoad(init);

                    compilation.EmitterResult.Emit("ADD", tmp, expr.Instance);
                    compilation.EmitterResult.Emit("DREF", tmp, tmp);

                    int targetLength = fdef.ParameterTypes != null
                                           ? fdef.ParameterTypes.Length
                                           : expr.ParameterList.Length;

                    externalSymbol?.SetUsed();
                    ExpressionTarget t = ParseFunctionInvocation(compilation, expr, targetLength, tmp, "JSREF");
                    compilation.ReleaseTempVar(tmp);

                    return(t);
                }
                else if (!isInternalFunc && externalSymbol == null)
                {
                    string funcEmit = target;

                    int targetLength = fdef.ParameterTypes?.Length ?? expr.ParameterList.Length;

                    if (expr.InstanceType != null &&
                        expr.InstanceType.StaticConstructor == expr.MemberDefinition &&
                        expr.WriteProlog &&
                        SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                        HlTypeConstructorPrologMode.Inline)
                    {
                        funcEmit = expr.InstanceType.GetInternalConstructor(compilation);
                    }

                    return(ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR"));
                }
            }

            if (isInternalFunc)
            {
                string funcEmit = target;

                FunctionData fData        = compilation.FunctionMap.Get(target);
                int          targetLength = fData.ParameterCount;

                //if (!expr.WriteProlog && SettingsManager.GetSettings < HlCompilerSettings >().ConstructorPrologMode ==
                //     HlTypeConstructorPrologMode.Inline )
                //{
                //    funcEmit = expr.MemberDefinition.
                //}

                if (expr.InstanceType != null &&
                    expr.InstanceType.StaticConstructor == expr.MemberDefinition &&
                    expr.WriteProlog &&
                    SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                    HlTypeConstructorPrologMode.Inline)
                {
                    funcEmit = expr.InstanceType.GetInternalConstructor(compilation);
                }

                fData.SetUsed();

                return(ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR").
                       Cast(
                           compilation.TypeSystem.GetType(
                               compilation.Root,
                               fData?.ReturnType ?? HLBaseTypeNames.s_UintTypeName
                               )
                           ));
            }

            if (externalSymbol != null)
            {
                string funcEmit = (externalSymbol as LinkedData)?.Info.Address.ToString() ?? target;

                FunctionData fData        = externalSymbol as FunctionData;
                int          targetLength = (externalSymbol as FunctionData)?.ParameterCount ?? expr.ParameterList.Length;

                if (expr.InstanceType != null &&
                    expr.InstanceType.StaticConstructor == expr.MemberDefinition &&
                    expr.WriteProlog &&
                    SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                    HlTypeConstructorPrologMode.Inline)
                {
                    funcEmit = expr.InstanceType.GetInternalConstructor(compilation);
                }

                externalSymbol.SetUsed();

                return(ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR").
                       Cast(compilation.TypeSystem.GetType(
                                compilation.Root,
                                fData?.ReturnType ?? HLBaseTypeNames.s_UintTypeName
                                )));
            }

            //if (isInternalFunc || externalSymbol != null)
            //{
            //    string funcEmit = externalSymbol is LinkedData l ? l.Info.Address.ToString() : target;

            //    int targetLength = isInternalFunc
            //                           ? compilation.FunctionMap.Get(target).ParameterCount
            //                           : (externalSymbol as FunctionData)?.ParameterCount ??
            //                             expr.ParameterList.Length;

            //    //if (!expr.WriteProlog && SettingsManager.GetSettings < HlCompilerSettings >().ConstructorPrologMode ==
            //    //     HlTypeConstructorPrologMode.Inline )
            //    //{
            //    //    funcEmit = expr.MemberDefinition.
            //    //}

            //    return ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR");
            //}

            if (compilation.ContainsVariable(target) ||
                compilation.ConstValTypes.Contains(target))
            {
                foreach (HlExpression parameter in expr.ParameterList)
                {
                    ExpressionTarget ttVal = compilation.Parse(parameter);
                    ExpressionTarget tt    = ttVal.MakeAddress(compilation);

                    compilation.EmitterResult.Emit(
                        $"PUSH",
                        tt.ResultAddress
                        );

                    compilation.ReleaseTempVar(tt.ResultAddress);
                    compilation.ReleaseTempVar(ttVal.ResultAddress);
                }

                if (compilation.ContainsVariable(target))
                {
                    compilation.EmitterResult.Emit($"JSREF", compilation.GetFinalName(target));
                }
                else
                {
                    compilation.EmitterResult.Emit($"JSREF", target);
                }

                ExpressionTarget tempReturn = new ExpressionTarget(
                    compilation.GetTempVarPop(),
                    true,
                    compilation.TypeSystem.GetType(
                        compilation.Root,
                        HLBaseTypeNames.s_UintTypeName
                        )
                    );

                return(tempReturn);
            }

            EventManager <ErrorEvent> .SendEvent(new FunctionNotFoundEvent( target ));

            return(new ExpressionTarget());
        }
Exemple #16
0
        public override ExpressionTarget ParseExpression(
            HlCompilation compilation,
            HlBinaryOp expr,
            ExpressionTarget outputTarget)
        {
            ExpressionTarget targetVal = compilation.Parse(
                expr.Left
                );
            ExpressionTarget rTargetVal = compilation.Parse(expr.Right);

            if (SettingsManager.GetSettings <HlCompilerSettings>().OptimizeConstExpressions&&
                !targetVal.IsAddress &&
                !rTargetVal.IsAddress &&
                targetVal.TypeDefinition.Name == HLBaseTypeNames.s_UintTypeName &&
                rTargetVal.TypeDefinition.Name == HLBaseTypeNames.s_UintTypeName)
            {
                return(ComputeStatic(compilation, targetVal, rTargetVal));
            }

            ExpressionTarget target  = targetVal.MakeAddress(compilation);
            ExpressionTarget rTarget = rTargetVal.MakeAddress(compilation);

            string instrKey =
                target.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName ||
                rTarget.TypeDefinition.Name == HLBaseTypeNames.s_FloatTypeName
                    ? InstructionKey + ".F"
                    : InstructionKey;

            if (target.IsPointer)
            {
                ExpressionTarget et = new ExpressionTarget(
                    compilation.GetTempVarDref(target.ResultAddress),
                    true,
                    target.TypeDefinition
                    );

                compilation.EmitterResult.Emit(
                    instrKey,
                    et.ResultAddress,
                    rTarget.ResultAddress,
                    outputTarget.ResultAddress
                    );

                compilation.ReleaseTempVar(et.ResultAddress);
                compilation.ReleaseTempVar(rTarget.ResultAddress);
                compilation.ReleaseTempVar(target.ResultAddress);
                compilation.ReleaseTempVar(targetVal.ResultAddress);
                compilation.ReleaseTempVar(rTargetVal.ResultAddress);

                return(outputTarget);
            }

            if (target.ResultAddress == outputTarget.ResultAddress)
            {
                compilation.EmitterResult.Emit(
                    instrKey,
                    target.ResultAddress,
                    rTarget.ResultAddress
                    );
            }
            else
            {
                compilation.EmitterResult.Emit(
                    instrKey,
                    target.ResultAddress,
                    rTarget.ResultAddress,
                    outputTarget.ResultAddress
                    );
            }

            compilation.ReleaseTempVar(rTarget.ResultAddress);
            compilation.ReleaseTempVar(target.ResultAddress);
            compilation.ReleaseTempVar(targetVal.ResultAddress);
            compilation.ReleaseTempVar(rTargetVal.ResultAddress);

            return(outputTarget);
        }
        public override ExpressionTarget ParseExpression(HlCompilation compilation, HlBinaryOp expr)
        {
            ExpressionTarget targetVal = compilation.Parse(
                expr.Left
                );
            ExpressionTarget target = targetVal.
                                      MakeAddress(compilation);

            ExpressionTarget rTargetVal = compilation.Parse(
                expr.Right,
                !target.IsPointer ? target : default
                );
            ExpressionTarget rTarget = rTargetVal.
                                       MakeAddress(compilation);

            if (rTarget.ResultAddress == target.ResultAddress)
            {
                return(target);
            }

            if (!rTarget.IsAddress && !target.IsPointer)
            {
                compilation.EmitterResult.Emit(
                    $"LOAD",
                    target.ResultAddress,
                    rTarget.ResultAddress
                    );

                compilation.ReleaseTempVar(rTarget.ResultAddress);
                compilation.ReleaseTempVar(rTargetVal.ResultAddress);

                return(target);
            }

            if (target.IsPointer)
            {
                if (rTarget.IsPointer)
                {
                    compilation.EmitterResult.Emit(
                        $"CREF",
                        rTarget.ResultAddress,
                        target.ResultAddress
                        );
                }
                else
                {
                    ExpressionTarget tmpTarget = new ExpressionTarget(
                        compilation.GetTempVarLoad(
                            rTarget.ResultAddress
                            ),
                        true,
                        compilation.TypeSystem.GetType(
                            compilation.Root,
                            HLBaseTypeNames.s_UintTypeName
                            )
                        );

                    compilation.EmitterResult.Emit(
                        $"CREF",
                        tmpTarget.ResultAddress,
                        target.ResultAddress
                        );

                    compilation.ReleaseTempVar(tmpTarget.ResultAddress);
                }
            }
            else
            {
                if (rTarget.IsPointer)
                {
                    ExpressionTarget tmpTarget = new ExpressionTarget(
                        compilation.GetTempVarLoad(
                            target.ResultAddress
                            ),
                        true,
                        compilation.TypeSystem.GetType(
                            compilation.Root,
                            HLBaseTypeNames.s_UintTypeName
                            )
                        );

                    compilation.EmitterResult.Emit(
                        $"CREF",
                        rTarget.ResultAddress,
                        tmpTarget.ResultAddress
                        );

                    compilation.ReleaseTempVar(tmpTarget.ResultAddress);
                }
                else if (rTarget.ResultAddress != target.ResultAddress)
                {
                    compilation.EmitterResult.Emit(
                        $"COPY",
                        rTarget.ResultAddress,
                        target.ResultAddress
                        );
                }
            }

            compilation.ReleaseTempVar(rTarget.ResultAddress);
            compilation.ReleaseTempVar(rTargetVal.ResultAddress);

            return(target);
        }