/// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            SymbolOperand callTargetOperand = this.GetInternalAllocateStringCallTarget(typeSystem);
            SymbolOperand methodTableOperand = new SymbolOperand(BuiltInSigType.IntPtr, StringClassMethodTableSymbolName);
            Operand lengthOperand = context.Operand1;
            Operand result = context.Result;

            context.SetInstruction(IR.Instruction.CallInstruction, result, callTargetOperand, methodTableOperand, lengthOperand);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Compares with the given operand for equality.
        /// </summary>
        /// <param name="other">The other operand to compare with.</param>
        /// <returns>The return value is true if the operands are equal; false if not.</returns>
        public override bool Equals(Operand other)
        {
            SymbolOperand lop = other as SymbolOperand;

            if (lop == null || lop.Type != Type)
            {
                return(false);
            }

            if (this.name == null && lop.name == null)
            {
                return(true);
            }

            return(this.name == lop.name);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Calls the specified target.
        /// </summary>
        /// <param name="symbolOperand">The symbol operand.</param>
        public void Call(SymbolOperand symbolOperand)
        {
            long address = _linker.Link(
                LinkType.RelativeOffset | LinkType.I4,
                _compiler.Method.ToString(),
                (int)(_codeStream.Position - _codeStreamBasePosition),
                (int)(_codeStream.Position - _codeStreamBasePosition) + 4,
                symbolOperand.Name,
                IntPtr.Zero
            );

            if (address == 0L)
            {
                this.WriteByte(0);
                this.WriteByte(0);
                this.WriteByte(0);
                this.WriteByte(0);
            }
            else
            {
                this._codeStream.Position += 4;
            }
        }
        private Operand InsertLoadBeforeInstruction(Context context, string symbolName, SigType type)
        {
            Context before = context.InsertBefore();
            Operand result = this.MethodCompiler.CreateTemporary(type);
            Operand op = new SymbolOperand(type, symbolName);

            before.SetInstruction(Instruction.Get(OpCode.Ldc_i4), result, op);

            return result;
        }
        /// <summary>
        /// Visitation function for Ldstr instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Ldstr(Context context)
        {
            /*
             * This requires a special memory layout for strings as they are interned by the compiler
             * into the generated image. This won't work this way forever: As soon as we'll support
             * a real AppDomain and real string interning, this code will have to go away and will
             * be replaced by a proper VM call.
             *
             */

            IAssemblyLinker linker = this.methodCompiler.Linker;
            IMetadataModule assembly = this.methodCompiler.Assembly;

            string referencedString = assembly.Metadata.ReadUserString(context.TokenType);

            string symbolName = @"$ldstr$" + assembly.Name + "$String" + context.TokenType.ToString("x");

            if (!linker.HasSymbol(symbolName))
            {
                const int nativePtrSize = 4;
                const int nativePtrAlignment = 4;

                int stringHeaderLength = nativePtrSize * 3;
                int stringDataLength = referencedString.Length * 2;

                // HACK: These strings should actually go into .rodata, but we can't link that right now.
                using (Stream stream = linker.Allocate(symbolName, SectionKind.Text, stringHeaderLength + stringDataLength, nativePtrAlignment))
                {
                    // Method table and sync block
                    stream.Write(new byte[8], 0, 8);

                    // String length field
                    stream.Write(BitConverter.GetBytes(referencedString.Length), 0, nativePtrSize);

                    // String data
                    byte[] stringData = Encoding.Unicode.GetBytes(referencedString);
                    Debug.Assert(stringData.Length == stringDataLength, @"Byte array of string data doesn't match expected string data length");
                    stream.Write(stringData, 0, stringData.Length);
                }

                string stringMethodTableSymbol = @"System.String$mtable";
                linker.Link(LinkType.AbsoluteAddress | LinkType.I4, symbolName, 0, 0, stringMethodTableSymbol, IntPtr.Zero);
            }

            Operand source = new SymbolOperand(BuiltInSigType.String, symbolName);
            Operand destination = context.Result;

            context.SetInstruction(Instruction.MoveInstruction, destination, source);
        }