/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { 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); }
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> /// Calls the specified target. /// </summary> /// <param name="symbolOperand">The symbol operand.</param> public void Call(SymbolOperand symbolOperand) { linker.Link( LinkType.RelativeOffset | LinkType.NativeI4, compiler.Method.ToString(), (int)(codeStream.Position - codeStreamBasePosition), (int)(codeStream.Position - codeStreamBasePosition) + 4, symbolOperand.Name, IntPtr.Zero ); codeStream.Position += 4; }
/// <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 = methodCompiler.Linker; IMetadataModule assembly = methodCompiler.Assembly; string referencedString = assembly.Metadata.ReadUserString(context.TokenType); string symbolName = @"$ldstr$" + assembly.Name + "$String" + context.TokenType.ToString("x"); if (!linker.HasSymbol(symbolName)) { // HACK: These strings should actually go into .rodata, but we can't link that right now. using (Stream stream = linker.Allocate(symbolName, SectionKind.Text, 0, nativePointerAlignment)) { // Method table and sync block linker.Link(LinkType.AbsoluteAddress | LinkType.NativeI4, symbolName, 0, 0, @"System.String$mtable", IntPtr.Zero); stream.WriteZeroBytes(8); // String length field stream.Write(BitConverter.GetBytes(referencedString.Length), 0, nativePointerSize); // String data byte[] stringData = Encoding.Unicode.GetBytes(referencedString); Debug.Assert(stringData.Length == referencedString.Length * 2, @"Byte array of string data doesn't match expected string data length"); stream.Write(stringData); } } Operand source = new SymbolOperand(BuiltInSigType.String, symbolName); Operand destination = context.Result; context.SetInstruction(IRInstruction.Move, destination, source); }