Ejemplo n.º 1
0
        private static bool MatchArgs(MethodInfo method, IList<TypeDefinition> argTypes)
        {
            if (method.Parameters.Count != argTypes.Count)
            {
                return false;
            }

            bool match = true;
            for (int i = 0; i < method.Parameters.Count; i++)
            {
                if (string.CompareOrdinal(method.Parameters[i].Type.FullName, argTypes[i].FullName) != 0)
                {
                    match = false;
                    break;
                }
            }

            return match;
        }
Ejemplo n.º 2
0
        public void AddProto(MethodInfo proto)
        {
            string mangledName = proto.MangledName;
            foreach (var existing in this.protoList)
            {
                if (string.CompareOrdinal(existing.MangledName, mangledName) == 0)
                {
                    return;
                }
            }

            this.protoList.Add(proto);
        }
Ejemplo n.º 3
0
        private bool TryCreateMethod(
            CompilerContext context, 
            TypeDefinition type,
            MethodDeclaration methodDecl, 
            out MethodInfo methodInfo)
        {
            methodInfo = new MethodInfo(type)
            {
                Name = methodDecl.MethodName,
                IsStatic = methodDecl.IsStatic,
                IsVirtual = methodDecl.IsVirtual || methodDecl.IsAbstract,
                IsAbstract = methodDecl.IsAbstract
            };

            TypeDefinition returnType = null;
            if (methodDecl.ReturnType != null)
            {
                if (!this.TryResolveTypeReference(context, methodDecl.ReturnType, out returnType))
                {
                    return false;
                }

                methodInfo.ReturnType = returnType;
            }

            foreach (ParameterDeclaration paramDecl in methodDecl.Parameters)
            {
                TypeDefinition paramDef = null;
                if (!this.TryResolveTypeReference(context, paramDecl.Type, out paramDef))
                {
                    return false;
                }

                foreach (string name in paramDecl.ParameterNames)
                {
                    ParameterInfo paramInfo = new ParameterInfo
                    {
                        Name = name,
                        Type = paramDef
                    };

                    methodInfo.Parameters.Add(paramInfo);
                }
            }

            if (methodInfo.IsVirtual)
            {
                methodInfo.AssignVTableIndex();
            }

            return true;
        }
Ejemplo n.º 4
0
        private bool TryEmitReference(
            ReferenceExpression referenceExpression,
            CompilerContext context,
            Scope scope,
            MethodImpl method,
            out string location,
            out TypeDefinition storageType,
            out MethodInfo calleeMethod)
        {
            calleeMethod = null;
            NamedReferenceExpression namedRef = referenceExpression as NamedReferenceExpression;
            if (namedRef != null)
            {
                SymbolEntry symbol = null;
                if (scope.TryLookup(namedRef.Identifier, out symbol))
                {
                    storageType = symbol.Type;
                    LocalVariable localVar = symbol as LocalVariable;
                    if (localVar != null)
                    {
                        location = string.Format("_{0}$[ebp]", localVar.Name);
                        return true;
                    }
                    else
                    {
                        ParameterVariable parVar = symbol as ParameterVariable;
                        if (parVar != null)
                        {
                            location = string.Format("_{0}$[ebp]", parVar.Name);
                            return true;
                        }
                    }
                }

                foreach (var field in method.Method.Type.Fields)
                {
                    if (string.CompareOrdinal(field.Name, namedRef.Identifier) == 0)
                    {
                        SymbolEntry symThis = null;
                        if(!scope.TryLookup("this", out symThis))
                        {
                            storageType = null;
                            location = null;
                            return false;
                        }

                        method.Statements.Add(
                            new AsmStatement
                            {
                                Instruction = "mov ecx,_this$[ebp]"
                            });
                        if (field.Offset > 0)
                        {
                            method.Statements.Add(
                                new AsmStatement { Instruction = "add ecx," + field.Offset });
                        }

                        storageType = field.Type;
                        location = "[ecx]";
                        return true;
                    }
                }

                foreach (var memberMethod in method.Method.Type.Methods)
                {
                    if (string.CompareOrdinal(memberMethod.Name, namedRef.Identifier) == 0)
                    {
                        method.Module.AddProto(memberMethod);
                        if (!memberMethod.IsStatic)
                        {
                            SymbolEntry symThis = null;
                            if (!scope.TryLookup("this", out symThis))
                            {
                                storageType = null;
                                location = null;
                                return false;
                            }

                            method.Statements.Add(
                                new AsmStatement
                                {
                                    Instruction = "mov ecx,_this$[ebp]"
                                });

                            method.Statements.Add(new AsmStatement { Instruction = "push ecx" });
                        }

                        if (memberMethod.IsVirtual)
                        {
                            location = "[ecx]";
                        }
                        else
                        {
                            location = memberMethod.MangledName;
                        }

                        storageType = memberMethod.ReturnType;
                        calleeMethod = memberMethod;
                        return true;
                    }
                }

                if (context.TryFindTypeByName(namedRef.Identifier, out storageType))
                {
                    location = null;
                    return true;
                }

                string message = string.Format(
                    Properties.Resources.CodeGenerator_UndeclaredIdentifier,
                    namedRef.Identifier);
                log.Write(new Message(
                    namedRef.Start.Path,
                    namedRef.Start.Line,
                    namedRef.Start.Column,
                    Severity.Error,
                    message));
            }

            MemberReferenceExpression memberRef = referenceExpression as MemberReferenceExpression;
            if (memberRef != null)
            {
                string innerLoc = null;
                TypeDefinition innerType = null;
                MethodInfo innerCalleeMethod = null;
                if (this.TryEmitReference(memberRef.Inner, context, scope, method, out innerLoc, out innerType, out innerCalleeMethod))
                {
                    foreach (var field in innerType.Fields)
                    {
                        if (string.CompareOrdinal(field.Name, memberRef.MemberName) == 0)
                        {
                            method.Statements.Add(
                                new AsmStatement
                                {
                                    Instruction = string.Format("lea ecx,{0}", innerLoc)
                                });
                            if (field.Offset > 0)
                            {
                                method.Statements.Add(
                                    new AsmStatement { Instruction = "add ecx," + field.Offset });
                            }

                            storageType = field.Type;
                            location = "[ecx]";
                            return true;
                        }
                    }

                    foreach (var memberMethod in innerType.Methods)
                    {
                        if (string.CompareOrdinal(memberMethod.Name, memberRef.MemberName) == 0)
                        {
                            method.Module.AddProto(memberMethod);
                            if (!memberMethod.IsStatic)
                            {
                                method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", innerLoc) });
                                method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                            }

                            if (memberMethod.IsVirtual && memberRef.UseVirtualDispatch)
                            {
                                location = "[eax]";
                            }
                            else
                            {
                                location = memberMethod.MangledName;
                            }

                            storageType = memberMethod.ReturnType;
                            calleeMethod = memberMethod;
                            return true;
                        }
                    }

                    string message = string.Format(
                        Properties.Resources.CodeGenerator_UndeclaredMember,
                        memberRef.MemberName,
                        innerType.FullName);
                    log.Write(new Message(
                        memberRef.Start.Path,
                        memberRef.Start.Line,
                        memberRef.Start.Column,
                        Severity.Error,
                        message));
                }
            }

            CallReferenceExpression callExpr = referenceExpression as CallReferenceExpression;
            if (callExpr != null)
            {
                location = null;
                return this.TryEmitExpression(callExpr, context, scope, method, out storageType);
            }

            ArrayIndexReferenceExpression arrayIndexExpr = referenceExpression as ArrayIndexReferenceExpression;
            if (arrayIndexExpr != null)
            {
                TypeDefinition indexType = null;
                if (!this.TryEmitExpression(
                    arrayIndexExpr.Index,
                    context,
                    scope,
                    method,
                    out indexType))
                {
                    location = null;
                    storageType = null;
                    return false;
                }

                if (indexType.IsFloatingPoint || indexType.IsArray || indexType.IsClass || indexType.IsPointer)
                {
                    this.log.Write(new Message(
                        arrayIndexExpr.Index.Start.Path,
                        arrayIndexExpr.Index.Start.Line,
                        arrayIndexExpr.Index.Start.Column,
                        Severity.Error,
                        Properties.Resources.CodeGenerator_ArrayIndexIntExpected));
                    location = null;
                    storageType = null;
                    return false;
                }

                method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                string innerLoc = null;
                TypeDefinition innerType = null;
                MethodInfo arrayCalleeMethod = null;
                if (!this.TryEmitReference(
                    arrayIndexExpr.Inner,
                    context,
                    scope,
                    method,
                    out innerLoc,
                    out innerType,
                    out arrayCalleeMethod))
                {
                    location = null;
                    storageType = null;
                    return false;
                }

                if (!innerType.IsArray)
                {
                    log.Write(new Message(
                        arrayIndexExpr.Inner.Start.Path,
                        arrayIndexExpr.Inner.Start.Line,
                        arrayIndexExpr.Inner.Start.Column,
                        Severity.Error,
                        Properties.Resources.CodeGenerator_ArrayTypeExpected));
                    location = null;
                    storageType = null;
                    return false;
                }

                if (innerType.Size > 4)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "lea ecx," + innerLoc });
                }
                else
                {
                    method.Statements.Add(new AsmStatement { Instruction = "mov ecx," + innerLoc });
                }

                method.Statements.Add(new AsmStatement { Instruction = "pop eax" });
                int elementSize = innerType.InnerType.Size;
                if(elementSize > 1)
                {
                    int shiftSize = 0;
                    switch(elementSize)
                    {
                        case 2:
                            shiftSize = 1;
                            break;
                        case 4:
                            shiftSize = 2;
                            break;
                        case 8:
                            shiftSize = 3;
                            break;
                        case 16:
                            shiftSize = 4;
                            break;
                        case 32:
                            shiftSize = 5;
                            break;
                        case 64:
                            shiftSize = 6;
                            break;
                        default:
                            method.Statements.Add(new AsmStatement { Instruction = string.Format("imul eax,{0}", elementSize) });
                            break;
                    }

                    if (shiftSize != 0)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("shl eax,{0}", shiftSize) });
                    }
                }

                method.Statements.Add(new AsmStatement { Instruction = "add ecx,eax" });
                location = "[ecx]";
                storageType = innerType.InnerType;
                return true;
            }

            DereferenceExpression derefExpr = referenceExpression as DereferenceExpression;
            if (derefExpr != null)
            {
                string innerLoc = null;
                TypeDefinition innerType = null;
                MethodInfo innerCall = null;
                if (!this.TryEmitReference(
                    derefExpr.Inner,
                    context,
                    scope,
                    method,
                    out innerLoc,
                    out innerType,
                    out innerCall))
                {
                    location = null;
                    storageType = null;
                    return false;
                }

                if (!innerType.IsPointer)
                {
                    log.Write(new Message(
                        derefExpr.Start.Path,
                        derefExpr.Start.Line,
                        derefExpr.Start.Column,
                        Severity.Error,
                        Properties.Resources.CodeGenerator_CannotDerefNonPointer));
                    location = null;
                    storageType = null;
                    return false;
                }

                method.Statements.Add(new AsmStatement { Instruction = "mov ecx," + innerLoc });
                location = "[ecx]";
                storageType = innerType.InnerType;
                return true;
            }

            InheritedReferenceExpression inhRefExpr = referenceExpression as InheritedReferenceExpression;
            if (inhRefExpr != null)
            {
                storageType = method.Method.Type.BaseClass;
                if (storageType == null)
                {
                    string message = string.Format(
                        System.Globalization.CultureInfo.CurrentCulture,
                        Properties.Resources.CodeGenerator_NoBaseTypeForInherited,
                        method.Method.Type.FullName);
                    this.log.Write(new Message(
                        inhRefExpr.Start.Path,
                        inhRefExpr.Start.Line,
                        inhRefExpr.Start.Column,
                        Severity.Error,
                        message));
                    location = null;
                    return false;
                }

                SymbolEntry thisSymbol = null;
                if (!scope.TryLookup("this", out thisSymbol))
                {
                    // reference a static on the base class.
                    location = null;
                }
                else
                {
                    location = "_this$[ebp]";
                }

                return true;
            }

            location = null;
            storageType = null;
            return false;
        }
Ejemplo n.º 5
0
        public bool TryFindMethodAndType(
            string methodNameRef, 
            IList<TypeDefinition> parameterTypes,
            out TypeDefinition type, 
            out MethodInfo methodInfo)
        {
            type = null;
            methodInfo = null;
            int methodStart = methodNameRef.LastIndexOf('.');
            if (methodStart < 0)
            {
                return false;
            }

            string methodName = methodNameRef.Substring(methodStart + 1);
            string typeName = methodNameRef.Substring(0, methodStart);
            if (!TryFindTypeByName(typeName, out type))
            {
                return false;
            }

            foreach (var test in type.Methods)
            {
                if (string.CompareOrdinal(test.Name, methodName) == 0)
                {
                    bool match = true;
                    if (test.Parameters.Count != parameterTypes.Count)
                    {
                        continue;
                    }

                    for (int i = 0; i < test.Parameters.Count; i++)
                    {
                        if (string.CompareOrdinal(test.Parameters[i].Type.FullName, parameterTypes[i].FullName) != 0)
                        {
                            match = false;
                            break;
                        }
                    }

                    if (!match)
                    {
                        continue;
                    }

                    methodInfo = test;
                    return true;
                }
            }

            return false;
        }
Ejemplo n.º 6
0
        public bool TryFindConstructor(
            TypeDefinition objectType,
            IList<TypeDefinition> parameterTypes,
            out MethodInfo methodInfo)
        {
            methodInfo = null;
            foreach (MethodInfo constructor in objectType.Methods.Where(e => string.CompareOrdinal("constructor", e.Name) == 0))
            {
                if (constructor.Parameters.Count != parameterTypes.Count)
                {
                    continue;
                }

                bool match = true;
                for (int i = 0; i < parameterTypes.Count; i++)
                {
                    if (string.CompareOrdinal(constructor.Parameters[i].Type.FullName, parameterTypes[i].FullName) != 0)
                    {
                        match = false;
                        break;
                    }
                }

                if (match)
                {
                    methodInfo = constructor;
                    return true;
                }
            }

            return false;
        }
Ejemplo n.º 7
0
        public Scope BeginScope(MethodInfo method)
        {
            Scope scope = new Scope();
            if (method.ReturnType != null)
            {
                LocalVariable returnVar = scope.DefineLocalVariable(method.Name, method.ReturnType);
                scope.ReturnVariable = returnVar;
                if (method.ReturnType.Size > 8 && !method.ReturnType.IsFloatingPoint || method.ReturnType.IsClass)
                {
                    scope.LargeReturnVariable = scope.DefineParameter(
                        "$result",
                        this.GetPointerType(method.ReturnType));
                }
            }

            if (!method.IsStatic)
            {
                scope.DefineParameter("this", this.GetPointerType(method.Type));
            }

            foreach (ParameterInfo parameterInfo in method.Parameters)
            {
                scope.DefineParameter(parameterInfo.Name, parameterInfo.Type);
            }

            return scope;
        }