/// <summary> /// Encodes <code>ldstr</code> instruction and its operand. /// </summary> public void LoadString(UserStringHandle handle) { OpCode(ILOpCode.Ldstr); Token(MetadataTokens.GetToken(handle)); }
/// <summary> /// Encodes a token. /// </summary> public void Token(EntityHandle handle) { Token(MetadataTokens.GetToken(handle)); }
public Handle GetGenerationHandle(Handle handle, out int generation) { if (handle.IsVirtual) { // TODO: if a virtual handle is connected to real handle then translate the rid, // otherwise return vhandle and base. throw new NotSupportedException(); } if (handle.IsHeapHandle) { int heapOffset = handle.Offset; HeapIndex heapIndex; MetadataTokens.TryGetHeapIndex(handle.Kind, out heapIndex); var sizes = _heapSizes[(int)heapIndex]; generation = sizes.BinarySearch(heapOffset); if (generation >= 0) { Debug.Assert(sizes[generation] == heapOffset); // the index points to the start of the next generation that added data to the heap: do { generation++; }while (generation < sizes.Length && sizes[generation] == heapOffset); } else { generation = ~generation; } if (generation >= sizes.Length) { throw new ArgumentException(SR.HandleBelongsToFutureGeneration, nameof(handle)); } // GUID heap accumulates - previous heap is copied to the next generation int relativeHeapOffset = (handle.Type == HandleType.Guid || generation == 0) ? heapOffset : heapOffset - sizes[generation - 1]; return(new Handle((byte)handle.Type, relativeHeapOffset)); } else { int rowId = handle.RowId; var sizes = _rowCounts[(int)handle.Type]; generation = sizes.BinarySearch(new RowCounts { AggregateInserts = rowId }); if (generation >= 0) { Debug.Assert(sizes[generation].AggregateInserts == rowId); // the row is in a generation that inserted exactly one row -- the one that we are looking for; // or it's in a preceding generation if the current one didn't insert any rows of the kind: while (generation > 0 && sizes[generation - 1].AggregateInserts == rowId) { generation--; } } else { // the row is in a generation that inserted multiple new rows: generation = ~generation; if (generation >= sizes.Length) { throw new ArgumentException(SR.HandleBelongsToFutureGeneration, nameof(handle)); } } // In each delta table updates always precede inserts. int relativeRowId = (generation == 0) ? rowId : rowId - sizes[generation - 1].AggregateInserts + sizes[generation].Updates; return(new Handle((byte)handle.Type, relativeRowId)); } }
/// <summary> /// Adds an exception clause. /// </summary> /// <param name="kind">Clause kind.</param> /// <param name="tryOffset">Try block start offset.</param> /// <param name="tryLength">Try block length.</param> /// <param name="handlerOffset">Handler start offset.</param> /// <param name="handlerLength">Handler length.</param> /// <param name="catchType"> /// <see cref="TypeDefinitionHandle"/>, <see cref="TypeReferenceHandle"/> or <see cref="TypeSpecificationHandle"/>, /// or nil if <paramref name="kind"/> is not <see cref="ExceptionRegionKind.Catch"/> /// </param> /// <param name="filterOffset"> /// Offset of the filter block, or 0 if the <paramref name="kind"/> is not <see cref="ExceptionRegionKind.Filter"/>. /// </param> /// <returns>Encoder for the next clause.</returns> /// <exception cref="ArgumentException"><paramref name="catchType"/> is invalid.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="kind"/> has invalid value.</exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="tryOffset"/>, <paramref name="tryLength"/>, <paramref name="handlerOffset"/> or <paramref name="handlerLength"/> is out of range. /// </exception> /// <exception cref="InvalidOperationException">Method body was not declared to have exception regions.</exception> public ExceptionRegionEncoder Add( ExceptionRegionKind kind, int tryOffset, int tryLength, int handlerOffset, int handlerLength, EntityHandle catchType = default(EntityHandle), int filterOffset = 0) { if (Builder == null) { Throw.InvalidOperation(SR.MethodHasNoExceptionRegions); } if (HasSmallFormat) { if (unchecked ((ushort)tryOffset) != tryOffset) { Throw.ArgumentOutOfRange(nameof(tryOffset)); } if (unchecked ((byte)tryLength) != tryLength) { Throw.ArgumentOutOfRange(nameof(tryLength)); } if (unchecked ((ushort)handlerOffset) != handlerOffset) { Throw.ArgumentOutOfRange(nameof(handlerOffset)); } if (unchecked ((byte)handlerLength) != handlerLength) { Throw.ArgumentOutOfRange(nameof(handlerLength)); } } else { if (tryOffset < 0) { Throw.ArgumentOutOfRange(nameof(tryOffset)); } if (tryLength < 0) { Throw.ArgumentOutOfRange(nameof(tryLength)); } if (handlerOffset < 0) { Throw.ArgumentOutOfRange(nameof(handlerOffset)); } if (handlerLength < 0) { Throw.ArgumentOutOfRange(nameof(handlerLength)); } } int catchTokenOrOffset; switch (kind) { case ExceptionRegionKind.Catch: if (!IsValidCatchTypeHandle(catchType)) { Throw.InvalidArgument_Handle(nameof(catchType)); } catchTokenOrOffset = MetadataTokens.GetToken(catchType); break; case ExceptionRegionKind.Filter: if (filterOffset < 0) { Throw.ArgumentOutOfRange(nameof(filterOffset)); } catchTokenOrOffset = filterOffset; break; case ExceptionRegionKind.Finally: case ExceptionRegionKind.Fault: catchTokenOrOffset = 0; break; default: throw new ArgumentOutOfRangeException(nameof(kind)); } AddUnchecked(kind, tryOffset, tryLength, handlerOffset, handlerLength, catchTokenOrOffset); return(this); }
public Handle GetGenerationHandle(Handle handle, out int generation) { if (handle.IsVirtual) { // TODO: if a virtual handle is connected to real handle then translate the rid, // otherwise return vhandle and base. throw new NotSupportedException(); } int rowId = (int)handle.RowId; uint typeId = handle.TokenType; int relativeRowId; if (handle.IsHeapHandle) { HeapIndex heapIndex; MetadataTokens.TryGetHeapIndex(handle.Kind, out heapIndex); var sizes = heapSizes[(int)heapIndex]; generation = sizes.BinarySearch(rowId); if (generation >= 0) { DebugCorlib.Assert(sizes[generation] == rowId); // the index points to the start of the next generation that added data to the heap: do { generation++; }while (generation < sizes.Length && sizes[generation] == rowId); } else { generation = ~generation; } if (generation >= sizes.Length) { throw new ArgumentException("Handle belongs to a future generation", "handle"); } // GUID heap accumulates - previous heap is copied to the next generation relativeRowId = (typeId == TokenTypeIds.Guid || generation == 0) ? rowId : rowId - sizes[generation - 1]; } else { var sizes = rowCounts[(int)handle.value >> TokenTypeIds.RowIdBitCount]; generation = sizes.BinarySearch(new RowCounts { AggregateInserts = rowId }); if (generation >= 0) { DebugCorlib.Assert(sizes[generation].AggregateInserts == rowId); // the row is in a generation that inserted exactly one row -- the one that we are looking for; // or it's in a preceeding generation if the current one didn't insert any rows of the kind: while (generation > 0 && sizes[generation - 1].AggregateInserts == rowId) { generation--; } } else { // the row is in a generation that inserted multiple new rows: generation = ~generation; if (generation >= sizes.Length) { throw new ArgumentException("Handle belongs to a future generation", "handle"); } } // In each delta table updates always precede inserts. relativeRowId = (generation == 0) ? rowId : rowId - sizes[generation - 1].AggregateInserts + sizes[generation].Updates; } return(new Handle(typeId | (uint)relativeRowId)); }