public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { if (relocsOnly) { return; } TargetArchitecture targetArch = factory.Target.Architecture; for (int frameInfoIndex = 0; frameInfoIndex < _methodNode.FrameInfos.Length; frameInfoIndex++) { byte[] unwindInfo = _methodNode.FrameInfos[frameInfoIndex].BlobData; if (targetArch == TargetArchitecture.X64) { // On Amd64, patch the first byte of the unwind info by setting the flags to EHANDLER | UHANDLER // as that's what CoreCLR does (zapcode.cpp, ZapUnwindData::Save). const byte UNW_FLAG_EHANDLER = 1; const byte UNW_FLAG_UHANDLER = 2; const byte FlagsShift = 3; unwindInfo[0] |= (byte)((UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER) << FlagsShift); } else if ((targetArch == TargetArchitecture.ARM) || (targetArch == TargetArchitecture.ARM64)) { // Set the 'X' bit to indicate that there is a personality routine associated with this method unwindInfo[2] |= 1 << 4; } dataBuilder.EmitBytes(unwindInfo); // 4-align after emitting the unwind info dataBuilder.EmitZeros(-unwindInfo.Length & 3); if (targetArch != TargetArchitecture.X86) { bool isFilterFunclet = (_methodNode.FrameInfos[frameInfoIndex].Flags & FrameInfoFlags.Filter) != 0; ISymbolNode personalityRoutine = (isFilterFunclet ? factory.FilterFuncletPersonalityRoutine : factory.PersonalityRoutine); int codeDelta = 0; if (targetArch == TargetArchitecture.ARM) { // THUMB_CODE codeDelta = 1; } dataBuilder.EmitReloc(personalityRoutine, RelocType.IMAGE_REL_BASED_ADDR32NB, codeDelta); } if (frameInfoIndex == 0 && _methodNode.GCInfo != null) { dataBuilder.EmitBytes(_methodNode.GCInfo); // Maintain 4-alignment for the next unwind / GC info block int align4Pad = -_methodNode.GCInfo.Length & 3; dataBuilder.EmitZeros(align4Pad); } } }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { if (relocsOnly) { return; } bool isFound = factory.RuntimeFunctionsGCInfo.Deduplicator.TryGetValue(this, out var found); if (isFound && (found != this)) { return; } factory.RuntimeFunctionsGCInfo.Deduplicator.Add(this); foreach (var item in EncodeDataCore(factory)) { if (item.Bytes != null) { dataBuilder.EmitBytes(item.Bytes); // Maintain 4-alignment for the next unwind / GC info block int align4Pad = -item.Bytes.Length & 3; dataBuilder.EmitZeros(align4Pad); } else { dataBuilder.EmitReloc(item.Symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, item.SymbolDelta); } } }
private void WriteMethodTableRvas(NodeFactory factory, ref ObjectDataBuilder builder, ref BlobReader reader) { MetadataReader metadataReader = _sourceModule.MetadataReader; var tableIndex = TableIndex.MethodDef; int rowCount = metadataReader.GetTableRowCount(tableIndex); int rowSize = metadataReader.GetTableRowSize(tableIndex); for (int i = 1; i <= rowCount; i++) { Debug.Assert(builder.CountBytes == reader.Offset); int inputRva = reader.ReadInt32(); if (inputRva == 0) { // Don't fix up 0 Rvas (abstract methods in the methodDef table) builder.EmitInt(0); } else { var methodDefHandle = MetadataTokens.EntityHandle(TableIndex.MethodDef, i); EcmaMethod method = _sourceModule.GetMethod(methodDefHandle) as EcmaMethod; builder.EmitReloc(((ReadyToRunCodegenNodeFactory)factory).CopiedMethodIL(method), RelocType.IMAGE_REL_BASED_ADDR32NB); } // Skip the rest of the row int remainingBytes = rowSize - sizeof(int); builder.EmitBytes(reader.ReadBytes(remainingBytes)); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.AddSymbol(this); builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName)); builder.EmitByte(0); // zero string terminator return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); builder.EmitBytes(Encoding.ASCII.GetBytes(_compilerIdentifier)); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName)); return(builder.ToObjectData()); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { if (relocsOnly) { return; } for (int frameInfoIndex = 0; frameInfoIndex < _methodNode.FrameInfos.Length; frameInfoIndex++) { byte[] unwindInfo = _methodNode.FrameInfos[frameInfoIndex].BlobData; if (factory.Target.Architecture == Internal.TypeSystem.TargetArchitecture.X64) { // On Amd64, patch the first byte of the unwind info by setting the flags to EHANDLER | UHANDLER // as that's what CoreCLR does (zapcode.cpp, ZapUnwindData::Save). const byte UNW_FLAG_EHANDLER = 1; const byte UNW_FLAG_UHANDLER = 2; const byte FlagsShift = 3; unwindInfo[0] |= (byte)((UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER) << FlagsShift); } dataBuilder.EmitBytes(unwindInfo); // 4-align after emitting the unwind info dataBuilder.EmitZeros(-unwindInfo.Length & 3); if (factory.Target.Architecture != Internal.TypeSystem.TargetArchitecture.X86) { bool isFilterFunclet = (_methodNode.FrameInfos[frameInfoIndex].Flags & FrameInfoFlags.Filter) != 0; ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory; ISymbolNode personalityRoutine = (isFilterFunclet ? r2rFactory.FilterFuncletPersonalityRoutine : r2rFactory.PersonalityRoutine); dataBuilder.EmitReloc(personalityRoutine, RelocType.IMAGE_REL_BASED_ADDR32NB); } if (frameInfoIndex == 0 && _methodNode.GCInfo != null) { dataBuilder.EmitBytes(_methodNode.GCInfo); // Maintain 4-alignment for the next unwind / GC info block int align4Pad = -_methodNode.GCInfo.Length & 3; dataBuilder.EmitZeros(align4Pad); } } }
public void WriteData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly = false) { int offset = Offset; if (FixupInfos != null) { int startOffset = builder.CountBytes; for (int i = 0; i < FixupInfos.Count; ++i) { var fixupInfo = FixupInfos[i]; // do we have overlapping fixups? if (fixupInfo.Offset < offset) { throw new BadImageFormatException(); } if (!relocsOnly) { // emit bytes before fixup builder.EmitBytes(Data, offset, fixupInfo.Offset - offset); } // write the fixup FixupInfos[i].WriteData(ref builder, factory); // move pointer past the fixup offset = Offset + builder.CountBytes - startOffset; } } if (offset > Data.Length) { throw new BadImageFormatException(); } if (!relocsOnly) { // Emit remaining bytes builder.EmitBytes(Data, offset, Data.Length - offset); } }
public unsafe override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); BlobReader metadataBlob = new BlobReader(_sourceModule.PEReader.GetMetadata().Pointer, _sourceModule.PEReader.GetMetadata().Length); var metadataReader = _sourceModule.MetadataReader; // // methodDef table // int methodDefTableOffset = metadataReader.GetTableMetadataOffset(TableIndex.MethodDef); builder.EmitBytes(metadataBlob.ReadBytes(methodDefTableOffset)); WriteMethodTableRvas(factory, ref builder, ref metadataBlob); // // fieldRva table // int fieldRvaTableOffset = metadataReader.GetTableMetadataOffset(TableIndex.FieldRva); builder.EmitBytes(metadataBlob.ReadBytes(fieldRvaTableOffset - metadataBlob.Offset)); WriteFieldRvas(factory, ref builder, ref metadataBlob); // Copy the rest of the metadata blob builder.EmitBytes(metadataBlob.ReadBytes(metadataReader.MetadataLength - metadataBlob.Offset)); Debug.Assert(builder.CountBytes == metadataBlob.Length); Debug.Assert(builder.CountBytes == metadataBlob.Offset); Debug.Assert(builder.CountBytes == Size); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); builder.EmitBytes(GetRvaData(factory.Target.PointerSize)); return(builder.ToObjectData()); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { ProfileDataNode nextElementInList = ((ProfileDataSectionNode)ContainingNode).NextElementToEncode; if (nextElementInList != null) { dataBuilder.EmitPointerReloc(nextElementInList, -OffsetFromStartOfObjectToSymbol); } else { dataBuilder.EmitZeroPointer(); } if (relocsOnly) { return; } EcmaMethod ecmaMethod = (EcmaMethod)_methodNode.Method.GetTypicalMethodDefinition(); int startOffset = dataBuilder.CountBytes; var reservation = dataBuilder.ReserveInt(); dataBuilder.EmitInt(0); // CORBBTPROF_METHOD_HEADER::cDetail dataBuilder.EmitInt(ecmaMethod.MetadataReader.GetToken(ecmaMethod.Handle)); // CORBBT_METHOD_INFO::token dataBuilder.EmitInt(_ilSize); // CORBBT_METHOD_INFO::ILSize dataBuilder.EmitInt(_blockCount); // CORBBT_METHOD_INFO::cBlock int sizeOfCORBBTPROF_METHOD_HEADER = dataBuilder.CountBytes - startOffset; Debug.Assert(sizeOfCORBBTPROF_METHOD_HEADER == (OffsetFromStartOfObjectToSymbol - _targetDetails.PointerSize)); dataBuilder.EmitInt(reservation, sizeOfCORBBTPROF_METHOD_HEADER + _profileData.Length); dataBuilder.EmitBytes(_profileData); while ((dataBuilder.CountBytes & (dataBuilder.TargetPointerSize - 1)) != 0) { dataBuilder.EmitByte(0); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(4); builder.AddSymbol(this); DirectoryEntry resourcesDirectory = _module.PEReader.PEHeaders.CorHeader.ResourcesDirectory; PEMemoryBlock block = _module.PEReader.GetSectionData(resourcesDirectory.RelativeVirtualAddress); builder.EmitBytes(block.GetReader().ReadBytes(resourcesDirectory.Size)); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } List <CustomAttributeEntry> customAttributeEntries = GetCustomAttributeEntries(); int countOfEntries = customAttributeEntries.Count; if (countOfEntries == 0) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Buckets have 8 entries uint minTableBucketCount = (uint)(countOfEntries / 8) + 1; uint bucketCount = 1; // Bucket count must be power of two while (bucketCount < minTableBucketCount) { bucketCount *= 2; } // Resize the array. bool tryAgainWithBiggerTable = false; int countOfRetries = 0; ushort[] pTable; do { tryAgainWithBiggerTable = false; uint actualSizeOfTable = bucketCount * 8; // Buckets have 8 entries in them pTable = new ushort[actualSizeOfTable]; uint[] state = new uint[] { 729055690, 833774698, 218408041, 493449127 }; // Attempt to fill table foreach (var customAttributeEntry in customAttributeEntries) { string name = customAttributeEntry.TypeNamespace + "." + customAttributeEntry.TypeName; // This hashing algorithm MUST match exactly the logic in NativeCuckooFilter int hashOfAttribute = ReadyToRunHashCode.NameHashCode(name); uint hash = unchecked ((uint)ReadyToRunHashCode.CombineTwoValuesIntoHash((uint)hashOfAttribute, (uint)customAttributeEntry.Parent)); ushort fingerprint = (ushort)(hash >> 16); if (fingerprint == 0) { fingerprint = 1; } uint bucketAIndex = hash % bucketCount; uint fingerprintHash = (uint)fingerprint; uint bucketBIndex = (bucketAIndex ^ (fingerprintHash % bucketCount)); Debug.Assert(bucketAIndex == (bucketBIndex ^ (fingerprintHash % bucketCount))); if ((XorShift128(state) & 1) != 0) // Randomly choose which bucket to attempt to fill first { uint temp = bucketAIndex; bucketAIndex = bucketBIndex; bucketBIndex = temp; } Func <uint, ushort, bool> hasEntryInBucket = (uint bucketIndex, ushort fprint) => { for (int i = 0; i < 8; i++) { if (pTable[(bucketIndex * 8) + i] == fprint) { return(true); } } return(false); }; Func <uint, bool> isEmptyEntryInBucket = (uint bucketIndex) => { for (int i = 0; i < 8; i++) { if (pTable[(bucketIndex * 8) + i] == 0) { return(true); } } return(false); }; Action <uint, ushort> fillEmptyEntryInBucket = (uint bucketIndex, ushort fprint) => { for (int i = 0; i < 8; i++) { if (pTable[(bucketIndex * 8) + i] == 0) { pTable[(bucketIndex * 8) + i] = fprint; return; } } Debug.Assert(false, "Not possible to reach here"); }; // Scan for pre-existing fingerprint entry in buckets if (hasEntryInBucket(bucketAIndex, fingerprint) || hasEntryInBucket(bucketBIndex, fingerprint)) { continue; } // Determine if there is space in a bucket to add a new entry if (isEmptyEntryInBucket(bucketAIndex)) { fillEmptyEntryInBucket(bucketAIndex, fingerprint); continue; } if (isEmptyEntryInBucket(bucketBIndex)) { fillEmptyEntryInBucket(bucketBIndex, fingerprint); continue; } bool success = false; int MaxNumKicks = 256; // Note, that bucketAIndex itself was chosen randomly above. for (int n = 0; !success && n < MaxNumKicks; n++) { // Randomly swap an entry in bucket bucketAIndex with fingerprint uint entryIndexInBucket = XorShift128(state) & 0x7; ushort temp = fingerprint; fingerprint = pTable[(bucketAIndex * 8) + entryIndexInBucket]; pTable[(bucketAIndex * 8) + entryIndexInBucket] = temp; // Find other bucket fingerprintHash = (uint)fingerprint; bucketAIndex = bucketAIndex ^ (fingerprintHash % bucketCount); if (isEmptyEntryInBucket(bucketAIndex)) { fillEmptyEntryInBucket(bucketAIndex, fingerprint); success = true; } } if (success) { continue; } tryAgainWithBiggerTable = true; } if (tryAgainWithBiggerTable) { // bucket entry kicking path requires bucket counts to be power of two in size due to use of xor to retrieve second hash bucketCount *= 2; } }while(tryAgainWithBiggerTable && ((countOfRetries++) < 2)); byte[] result; if (tryAgainWithBiggerTable) { result = Array.Empty <byte>(); } else { result = new byte[pTable.Length * 2]; for (int i = 0; i < pTable.Length; i++) { result[i * 2] = (byte)(pTable[i] % 256); result[i * 2 + 1] = (byte)(pTable[i] >> 8); } } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(16); builder.AddSymbol(this); builder.EmitBytes(result); return(builder.ToObjectData());; }
public void WriteResources(ISymbolNode nodeAssociatedWithDataBuilder, ref ObjectDataBuilder dataBuilder) { Debug.Assert(dataBuilder.CountBytes == 0); SortedDictionary <string, List <ObjectDataBuilder.Reservation> > nameTable = new SortedDictionary <string, List <ObjectDataBuilder.Reservation> >(); Dictionary <ResLanguage, int> dataEntryTable = new Dictionary <ResLanguage, int>(); List <Tuple <ResType, ObjectDataBuilder.Reservation> > resTypes = new List <Tuple <ResType, ObjectDataBuilder.Reservation> >(); List <Tuple <ResName, ObjectDataBuilder.Reservation> > resNames = new List <Tuple <ResName, ObjectDataBuilder.Reservation> >(); List <Tuple <ResLanguage, ObjectDataBuilder.Reservation> > resLanguages = new List <Tuple <ResLanguage, ObjectDataBuilder.Reservation> >(); IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, checked ((ushort)_resTypeHeadName.Count), checked ((ushort)_resTypeHeadID.Count)); foreach (KeyValuePair <string, ResType> res in _resTypeHeadName) { resTypes.Add(new Tuple <ResType, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key, nameTable))); } foreach (KeyValuePair <ushort, ResType> res in _resTypeHeadID) { resTypes.Add(new Tuple <ResType, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key))); } foreach (Tuple <ResType, ObjectDataBuilder.Reservation> type in resTypes) { dataBuilder.EmitUInt(type.Item2, (uint)dataBuilder.CountBytes | 0x80000000); IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, checked ((ushort)type.Item1.NameHeadName.Count), checked ((ushort)type.Item1.NameHeadID.Count)); foreach (KeyValuePair <string, ResName> res in type.Item1.NameHeadName) { resNames.Add(new Tuple <ResName, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key, nameTable))); } foreach (KeyValuePair <ushort, ResName> res in type.Item1.NameHeadID) { resNames.Add(new Tuple <ResName, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key))); } } foreach (Tuple <ResName, ObjectDataBuilder.Reservation> type in resNames) { dataBuilder.EmitUInt(type.Item2, (uint)dataBuilder.CountBytes | 0x80000000); IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, 0, checked ((ushort)type.Item1.Languages.Count)); foreach (KeyValuePair <ushort, ResLanguage> res in type.Item1.Languages) { resLanguages.Add(new Tuple <ResLanguage, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key))); } } // Emit name table dataBuilder.PadAlignment(2); // name table is 2 byte aligned foreach (KeyValuePair <string, List <ObjectDataBuilder.Reservation> > name in nameTable) { foreach (ObjectDataBuilder.Reservation reservation in name.Value) { dataBuilder.EmitUInt(reservation, (uint)dataBuilder.CountBytes | 0x80000000); } dataBuilder.EmitUShort(checked ((ushort)name.Key.Length)); foreach (char c in name.Key) { dataBuilder.EmitUShort((ushort)c); } } // Emit byte arrays of resource data, capture the offsets foreach (Tuple <ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages) { dataBuilder.PadAlignment(4); // Data in resource files is 4 byte aligned dataEntryTable.Add(language.Item1, dataBuilder.CountBytes); dataBuilder.EmitBytes(language.Item1.DataEntry); } dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned foreach (Tuple <ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages) { dataBuilder.EmitInt(language.Item2, dataBuilder.CountBytes); IMAGE_RESOURCE_DATA_ENTRY.Write(ref dataBuilder, nodeAssociatedWithDataBuilder, dataEntryTable[language.Item1], language.Item1.DataEntry.Length); } dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned }
private void ComputeDependencyNodeDependencies(List <DependencyNodeCore <NodeFactory> > obj) { foreach (MethodCodeNode methodCodeNodeNeedingCode in obj) { MethodDesc method = methodCodeNodeNeedingCode.Method; string methodName = method.ToString(); Log.WriteLine("Compiling " + methodName); var methodIL = _ilProvider.GetMethodIL(method); if (methodIL == null) { return; } MethodCode methodCode; try { if (_skipJitList.Contains(new TypeAndMethod(method.OwningType.Name, method.Name))) { throw new NotImplementedException("SkipJIT"); } methodCode = _corInfo.CompileMethod(method); if (methodCode.Relocs != null) { if (methodCode.Relocs.Any(r => r.Target is FieldDesc)) { // We only support FieldDesc for InitializeArray intrinsic right now. throw new NotImplementedException("RuntimeFieldHandle is not implemented"); } } } catch (Exception e) { Log.WriteLine("*** " + e.Message + " (" + method + ")"); // Call the __not_yet_implemented method DependencyAnalysis.X64.X64Emitter emit = new DependencyAnalysis.X64.X64Emitter(_nodeFactory); emit.Builder.RequireAlignment(_nodeFactory.Target.MinimumFunctionAlignment); emit.Builder.DefinedSymbols.Add(methodCodeNodeNeedingCode); emit.EmitLEAQ(emit.TargetRegister.Arg0, _nodeFactory.StringIndirection(method.ToString())); DependencyAnalysis.X64.AddrMode loadFromArg0 = new DependencyAnalysis.X64.AddrMode(emit.TargetRegister.Arg0, null, 0, 0, DependencyAnalysis.X64.AddrModeSize.Int64); emit.EmitMOV(emit.TargetRegister.Arg0, ref loadFromArg0); emit.EmitMOV(emit.TargetRegister.Arg0, ref loadFromArg0); emit.EmitLEAQ(emit.TargetRegister.Arg1, _nodeFactory.StringIndirection(e.Message)); DependencyAnalysis.X64.AddrMode loadFromArg1 = new DependencyAnalysis.X64.AddrMode(emit.TargetRegister.Arg1, null, 0, 0, DependencyAnalysis.X64.AddrModeSize.Int64); emit.EmitMOV(emit.TargetRegister.Arg1, ref loadFromArg1); emit.EmitMOV(emit.TargetRegister.Arg1, ref loadFromArg1); emit.EmitJMP(_nodeFactory.ExternSymbol("__not_yet_implemented")); methodCodeNodeNeedingCode.SetCode(emit.Builder.ToObjectData()); continue; } ObjectDataBuilder objData = new ObjectDataBuilder(); objData.Alignment = _nodeFactory.Target.MinimumFunctionAlignment; objData.EmitBytes(methodCode.Code); objData.DefinedSymbols.Add(methodCodeNodeNeedingCode); BlobNode readOnlyDataBlob = null; if (methodCode.ROData != null) { readOnlyDataBlob = _nodeFactory.ReadOnlyDataBlob( "__readonlydata_" + _nameMangler.GetMangledMethodName(method), methodCode.ROData, methodCode.RODataAlignment); } if (methodCode.Relocs != null) { for (int i = 0; i < methodCode.Relocs.Length; i++) { // TODO: Arbitrary relocs if (methodCode.Relocs[i].Block != BlockType.Code) { throw new NotImplementedException(); } int offset = methodCode.Relocs[i].Offset; int delta = methodCode.Relocs[i].Delta; RelocType relocType = (RelocType)methodCode.Relocs[i].RelocType; ISymbolNode targetNode; object target = methodCode.Relocs[i].Target; if (target is MethodDesc) { targetNode = _nodeFactory.MethodEntrypoint((MethodDesc)target); } else if (target is ReadyToRunHelper) { targetNode = _nodeFactory.ReadyToRunHelper((ReadyToRunHelper)target); } else if (target is JitHelper) { targetNode = _nodeFactory.ExternSymbol(((JitHelper)target).MangledName); } else if (target is string) { targetNode = _nodeFactory.StringIndirection((string)target); } else if (target is TypeDesc) { targetNode = _nodeFactory.NecessaryTypeSymbol((TypeDesc)target); } else if (target is RvaFieldData) { var rvaFieldData = (RvaFieldData)target; targetNode = _nodeFactory.ReadOnlyDataBlob(rvaFieldData.MangledName, rvaFieldData.Data, _typeSystemContext.Target.PointerSize); } else if (target is BlockRelativeTarget) { var blockRelativeTarget = (BlockRelativeTarget)target; // TODO: Arbitrary block relative relocs if (blockRelativeTarget.Block != BlockType.ROData) { throw new NotImplementedException(); } targetNode = readOnlyDataBlob; } else { // TODO: throw new NotImplementedException(); } objData.AddRelocAtOffset(targetNode, relocType, offset, delta); } } // TODO: ColdCode if (methodCode.ColdCode != null) { throw new NotImplementedException(); } methodCodeNodeNeedingCode.SetCode(objData.ToObjectData()); methodCodeNodeNeedingCode.InitializeFrameInfos(methodCode.FrameInfos); methodCodeNodeNeedingCode.InitializeDebugLocInfos(methodCode.DebugLocInfos); } }