Beispiel #1
0
 public MethodInfo GetCopyConstructor(CompilerContext context)
 {
     List<TypeDefinition> argTypes = new List<TypeDefinition>();
     argTypes.Add(context.GetPointerType(this));
     return FindConstructor(argTypes);
 }
Beispiel #2
0
        private bool TryResolveTypeReference(
            CompilerContext context, 
            TypeReference typeRef, 
            out TypeDefinition typeDef)
        {
            NamedTypeReference namedType = typeRef as NamedTypeReference;
            if (namedType != null)
            {
                if (!context.TryFindTypeByName(namedType.TypeName, out typeDef))
                {
                    string message = string.Format(
                        Properties.Resources.CodeGenerator_UndefinedType,
                        namedType.TypeName);
                    this.log.Write(new Message(
                        namedType.Start.Path,
                        namedType.Start.Line,
                        namedType.Start.Column,
                        Severity.Error,
                        message));
                    return false;
                }

                return true;
            }

            PointerTypeReference pointerType = typeRef as PointerTypeReference;
            if (pointerType != null)
            {
                TypeDefinition innerType = null;
                if (!this.TryResolveTypeReference(context, pointerType.ElementType, out innerType))
                {
                    typeDef = null;
                    return false;
                }

                typeDef = context.GetPointerType(innerType);
                return true;
            }

            ArrayTypeReference arrayType = typeRef as ArrayTypeReference;
            if (arrayType != null)
            {
                TypeDefinition innerType = null;
                if (!this.TryResolveTypeReference(context, arrayType.ElementType, out innerType))
                {
                    typeDef = null;
                    return false;
                }

                int elementCount = 0;
                if (arrayType.ElementCount != null)
                {
                    LiteralExpression litElementCount = arrayType.ElementCount as LiteralExpression;
                    if (litElementCount == null || !(litElementCount.Value is int))
                    {
                        log.Write(new Message(
                            arrayType.ElementCount.Start.Path,
                            arrayType.ElementCount.Start.Line,
                            arrayType.ElementCount.Start.Column,
                            Severity.Error,
                            Properties.Resources.CodeGenerator_ArrayTypeIntElementExpected));
                        typeDef = null;
                        return false;
                    }

                    elementCount = (int)(litElementCount.Value);
                }

                typeDef = context.GetArrayType(innerType, elementCount);
                return true;
            }

            typeDef = null;
            return false;
        }
Beispiel #3
0
        private bool TryEmitAddressExpression(
            AddressExpression addrExpr,
            CompilerContext context,
            Scope scope,
            MethodImpl method,
            out TypeDefinition valueType)
        {
            string innerLoc = null;
            TypeDefinition storageType = null;
            MethodInfo calleeMethod = null;
            if (!this.TryEmitReference(addrExpr.Inner, context, scope, method, out innerLoc, out storageType, out calleeMethod))
            {
                valueType = null;
                return false;
            }

            method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", innerLoc) });
            valueType = context.GetPointerType(storageType);
            return true;
        }
Beispiel #4
0
        private bool TryEmitNewExpression(
            NewExpression newExpr, 
            CompilerContext context, 
            Scope scope, 
            MethodImpl method, 
            out TypeDefinition valueType)
        {
            valueType = null;
            TypeDefinition objectType = null;
            if (!this.TryResolveTypeReference(context, newExpr.Type, out objectType))
            {
                valueType = null;
                return false;
            }

            if (!objectType.IsClass && newExpr.ConstructorArguments.Count() > 0)
            {
                log.Write(new Message(
                    newExpr.Start.Path,
                    newExpr.Start.Line,
                    newExpr.Start.Column,
                    Severity.Error,
                    Properties.Resources.CodeGenerator_ConstructorArgumentsAreOnlySupportedOnClassTypes));
                return false;
            }

            valueType = context.GetPointerType(objectType);

            if (!this.TryEmitAllocCall(newExpr.Start, context, scope, method, objectType.Size))
            {
                return false;
            }

            MethodInfo constructor = null;
            int argSize = 0;
            if (objectType.IsClass)
            {
                int nullTestStart = method.Statements.Count;
                List<TypeDefinition> argTypes = new List<TypeDefinition>();
                foreach (Expression arg in newExpr.ConstructorArguments.Reverse())
                {
                    TypeDefinition argType = null;
                    if (!this.TryEmitExpression(arg, context, scope, method, out argType))
                    {
                        return false;
                    }

                    this.PushResult(method, argType);
                    argSize += ((argType.Size + 3) / 4) * 4;
                    argTypes.Insert(0, argType);
                }

                if (!context.TryFindConstructor(objectType, argTypes, out constructor))
                {
                    // ok to have no default constructor
                    if (argTypes.Count > 0)
                    {
                        string message = string.Format(
                            System.Globalization.CultureInfo.CurrentCulture,
                            Properties.Resources.CodeGenerator_CannotFindConstructor,
                            objectType.FullName);
                        log.Write(new Message(
                            newExpr.Start.Path,
                            newExpr.Start.Line,
                            newExpr.Start.Column,
                            Severity.Error,
                            message));
                        return false;
                    }
                }

                if (constructor != null)
                {
                    LocalVariable tempPtr = scope.DefineTempVariable(valueType);
                    string jumpLabel = method.Module.GetNextJumpLabel();
                    List<AsmStatement> saveAlloc = new List<AsmStatement>();
                    saveAlloc.Add(new AsmStatement { Instruction = string.Format("mov _{0}$[ebp],eax", tempPtr.Name) });
                    saveAlloc.Add(new AsmStatement { Instruction = "test eax,eax" });
                    saveAlloc.Add(new AsmStatement { Instruction = "jz " + jumpLabel });
                    method.Statements.InsertRange(nullTestStart, saveAlloc);
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("mov eax,_{0}$[ebp]", tempPtr.Name) });
                    method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                    method.Module.AddProto(constructor);
                    method.Statements.Add(new AsmStatement { Instruction = "call " + constructor.MangledName });
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("add esp,{0}", argSize + 4) });
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("mov eax,_{0}$[ebp]", tempPtr.Name), Label = jumpLabel });
                }
            }

            return true;
        }