Exemple #1
0
        private static int GetClassConstructorContextStorageSize(TargetDetails target, MetadataType type)
        {
            int alignmentRequired = Math.Max(type.NonGCStaticFieldAlignment.AsInt, GetClassConstructorContextAlignment(target));

            return(AlignmentHelper.AlignUp(GetClassConstructorContextSize(type.Context.Target), alignmentRequired));
        }
        public void Pad(int size, int alignment, int expected)
        {
            int result = AlignmentHelper.Pad(size, alignment);

            Assert.AreEqual(result, expected);
        }
        private static async Task <Document> FixWhitespaceAsync(Document document, Diagnostic diagnostic, double dAlignmentStandardDeviation, CancellationToken cancellationToken)
        {
            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            int nCharToAdd = await AlignmentHelper.AdditionalSpacesToAddForConditionAsync(root, diagnostic, dAlignmentStandardDeviation, AlignmentHelper.IsSimpleAssignment, SyntaxKind.EqualsToken, cancellationToken).ConfigureAwait(false);

            var newText = text.Replace(new TextSpan(diagnostic.Location.SourceSpan.Start, 0), AlignmentHelper.WhiteSpaceString(nCharToAdd));

            return(document.WithText(newText));
        }
            protected override async Task <SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray <Diagnostic> diagnostics)
            {
                if (diagnostics.IsEmpty)
                {
                    return(null);
                }

                var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, fixAllContext.CancellationToken);
                var text     = await document.GetTextAsync().ConfigureAwait(false);

                SyntaxNode root = await document.GetSyntaxRootAsync().ConfigureAwait(false);

                for (int nDiagnostic = diagnostics.Length; nDiagnostic-- > 0;)
                {
                    var diagnostic = diagnostics[nDiagnostic];
                    int nCharToAdd = await AlignmentHelper.AdditionalSpacesToAddForConditionAsync(root, diagnostic, settings.AlignmentRules.AlignmentStandardDeviation, AlignmentHelper.IsSimpleAssignment, SyntaxKind.EqualsToken, fixAllContext.CancellationToken).ConfigureAwait(false);

                    text = text.Replace(new TextSpan(diagnostic.Location.SourceSpan.Start, 0), AlignmentHelper.WhiteSpaceString(nCharToAdd));
                }

                var tree = await document.GetSyntaxTreeAsync().ConfigureAwait(false);

                return(await tree.WithChangedText(text).GetRootAsync().ConfigureAwait(false));
            }
Exemple #5
0
        /// <summary>
        /// Output the section with a given name. For sections existent in the source MSIL PE file
        /// (.text, optionally .rsrc and .reloc), we first copy the content of the input MSIL PE file
        /// and then call the section serialization callback to emit the extra content after the input
        /// section content.
        /// </summary>
        /// <param name="name">Section name</param>
        /// <param name="location">RVA and file location where the section will be put</param>
        /// <returns>Blob builder representing the section data</returns>
        protected override BlobBuilder SerializeSection(string name, SectionLocation location)
        {
            BlobBuilder sectionDataBuilder = null;
            bool        haveCustomSection  = _customSections.Contains(name);
            int         sectionStartRva    = location.RelativeVirtualAddress;

            int outputSectionIndex = _sections.Length - 1;

            while (outputSectionIndex >= 0 && _sections[outputSectionIndex].Name != name)
            {
                outputSectionIndex--;
            }

            if (!_target.IsWindows)
            {
                if (outputSectionIndex > 0)
                {
                    sectionStartRva = Math.Max(sectionStartRva, _sectionRVAs[outputSectionIndex - 1] + _sectionRawSizes[outputSectionIndex - 1]);
                }

                const int RVAAlign = 1 << RVABitsToMatchFilePos;
                sectionStartRva = AlignmentHelper.AlignUp(sectionStartRva, RVAAlign);

                int rvaAdjust = (location.PointerToRawData - sectionStartRva) & (RVAAlign - 1);
                sectionStartRva += rvaAdjust;
                location         = new SectionLocation(sectionStartRva, location.PointerToRawData);
            }

            if (outputSectionIndex >= 0)
            {
                _sectionRVAs[outputSectionIndex] = sectionStartRva;
            }

            int inputSectionIndex = _peReader.PEHeaders.SectionHeaders.Count() - 1;

            while (inputSectionIndex >= 0 && _peReader.PEHeaders.SectionHeaders[inputSectionIndex].Name != name)
            {
                inputSectionIndex--;
            }
            if (inputSectionIndex >= 0)
            {
                SectionHeader sectionHeader = _peReader.PEHeaders.SectionHeaders[inputSectionIndex];
                int           sectionOffset = (_peReader.IsLoadedImage ? sectionHeader.VirtualAddress : sectionHeader.PointerToRawData);
                int           rvaDelta      = location.RelativeVirtualAddress - sectionHeader.VirtualAddress;

                _sectionRvaDeltas.Add(new SectionRVADelta(
                                          startRVA: sectionHeader.VirtualAddress,
                                          endRVA: sectionHeader.VirtualAddress + Math.Max(sectionHeader.VirtualSize, sectionHeader.SizeOfRawData),
                                          deltaRVA: rvaDelta));

                unsafe
                {
                    int        bytesToRead        = Math.Min(sectionHeader.SizeOfRawData, sectionHeader.VirtualSize);
                    BlobReader inputSectionReader = _peReader.GetEntireImage().GetReader(sectionOffset, bytesToRead);

                    if (name == ".rsrc")
                    {
                        // There seems to be a bug in BlobBuilder - when we LinkSuffix to an empty blob builder,
                        // the blob data goes out of sync and WriteContentTo outputs garbage.
                        sectionDataBuilder = PEResourceHelper.Relocate(inputSectionReader, rvaDelta);
                    }
                    else
                    {
                        sectionDataBuilder = new BlobBuilder();
                        sectionDataBuilder.WriteBytes(inputSectionReader.CurrentPointer, inputSectionReader.RemainingBytes);
                    }

                    int metadataRvaDelta = _peReader.PEHeaders.CorHeader.MetadataDirectory.RelativeVirtualAddress - sectionHeader.VirtualAddress;
                    if (metadataRvaDelta >= 0 && metadataRvaDelta < bytesToRead)
                    {
                        _metadataFileOffset = location.PointerToRawData + metadataRvaDelta;
                    }

                    int corHeaderRvaDelta = _peReader.PEHeaders.PEHeader.CorHeaderTableDirectory.RelativeVirtualAddress - sectionHeader.VirtualAddress;
                    if (corHeaderRvaDelta >= 0 && corHeaderRvaDelta < bytesToRead)
                    {
                        // Assume COR header resides in this section, deserialize it and store its location
                        _corHeaderFileOffset      = location.PointerToRawData + corHeaderRvaDelta;
                        inputSectionReader.Offset = corHeaderRvaDelta;
                        _corHeaderBuilder         = new CorHeaderBuilder(ref inputSectionReader);
                    }

                    int alignedSize = sectionHeader.VirtualSize;

                    // When custom section data is present, align the section size to 4K to prevent
                    // pre-generated MSIL relocations from tampering with native relocations.
                    if (_customSections.Contains(name))
                    {
                        alignedSize = (alignedSize + 0xFFF) & ~0xFFF;
                    }

                    if (alignedSize > bytesToRead)
                    {
                        // If the number of bytes read from the source PE file is less than the virtual size,
                        // zero pad to the end of virtual size before emitting extra section data
                        sectionDataBuilder.WriteBytes(0, alignedSize - bytesToRead);
                    }
                    location = new SectionLocation(
                        location.RelativeVirtualAddress + sectionDataBuilder.Count,
                        location.PointerToRawData + sectionDataBuilder.Count);
                }
            }

            BlobBuilder extraData = _sectionBuilder.SerializeSection(name, location, sectionStartRva);

            if (extraData != null)
            {
                if (sectionDataBuilder == null)
                {
                    // See above - there's a bug due to which LinkSuffix to an empty BlobBuilder screws up the blob content.
                    sectionDataBuilder = extraData;
                }
                else
                {
                    sectionDataBuilder.LinkSuffix(extraData);
                }
            }

            // Make sure the section has at least 1 byte, otherwise the PE emitter goes mad,
            // messes up the section map and corrups the output executable.
            if (sectionDataBuilder == null)
            {
                sectionDataBuilder = new BlobBuilder();
            }

            if (sectionDataBuilder.Count == 0)
            {
                sectionDataBuilder.WriteByte(0);
            }

            if (outputSectionIndex >= 0)
            {
                _sectionRawSizes[outputSectionIndex] = sectionDataBuilder.Count;
            }

            return(sectionDataBuilder);
        }
Exemple #6
0
        /// <summary>
        /// Output the section with a given name. For sections existent in the source MSIL PE file
        /// (.text, optionally .rsrc and .reloc), we first copy the content of the input MSIL PE file
        /// and then call the section serialization callback to emit the extra content after the input
        /// section content.
        /// </summary>
        /// <param name="name">Section name</param>
        /// <param name="location">RVA and file location where the section will be put</param>
        /// <returns>Blob builder representing the section data</returns>
        protected override BlobBuilder SerializeSection(string name, SectionLocation location)
        {
            BlobBuilder sectionDataBuilder = null;
            int         sectionStartRva    = location.RelativeVirtualAddress;

            int outputSectionIndex = _sections.Length - 1;

            while (outputSectionIndex >= 0 && _sections[outputSectionIndex].Name != name)
            {
                outputSectionIndex--;
            }

            if (!_target.IsWindows)
            {
                if (outputSectionIndex > 0)
                {
                    sectionStartRva = Math.Max(sectionStartRva, _sectionRVAs[outputSectionIndex - 1] + _sectionRawSizes[outputSectionIndex - 1]);
                }

                const int RVAAlign = 1 << RVABitsToMatchFilePos;
                sectionStartRva = AlignmentHelper.AlignUp(sectionStartRva, RVAAlign);

                int rvaAdjust = (location.PointerToRawData - sectionStartRva) & (RVAAlign - 1);
                sectionStartRva += rvaAdjust;
                location         = new SectionLocation(sectionStartRva, location.PointerToRawData);
            }

            if (outputSectionIndex >= 0)
            {
                _sectionRVAs[outputSectionIndex] = sectionStartRva;
            }

            BlobBuilder extraData = _sectionBuilder.SerializeSection(name, location);

            if (extraData != null)
            {
                if (sectionDataBuilder == null)
                {
                    // See above - there's a bug due to which LinkSuffix to an empty BlobBuilder screws up the blob content.
                    sectionDataBuilder = extraData;
                }
                else
                {
                    sectionDataBuilder.LinkSuffix(extraData);
                }
            }

            // Make sure the section has at least 1 byte, otherwise the PE emitter goes mad,
            // messes up the section map and corrups the output executable.
            if (sectionDataBuilder == null)
            {
                sectionDataBuilder = new BlobBuilder();
            }

            if (sectionDataBuilder.Count == 0)
            {
                sectionDataBuilder.WriteByte(0);
            }

            if (outputSectionIndex >= 0)
            {
                _sectionRawSizes[outputSectionIndex] = sectionDataBuilder.Count;
            }

            return(sectionDataBuilder);
        }
 private static unsafe int GetPaddedSize()
 {
     return(AlignmentHelper.Pad(sizeof(T), ElementAlignment));
 }
Exemple #8
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
        {
            ObjectDataBuilder objData = new ObjectDataBuilder(factory);

            objData.Alignment = 16;
            objData.DefinedSymbols.Add(this);
            if (_type.IsArray)
            {
                objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); // m_ComponentSize
                objData.EmitShort(0x4);                                                    // m_flags: IsArray(0x4)
            }
            else if (_type.IsString)
            {
                objData.EmitShort(2); // m_ComponentSize
                objData.EmitShort(0); // m_flags: 0
            }
            else
            {
                objData.EmitShort(0); // m_ComponentSize
                objData.EmitShort(0); // m_flags: 0
            }

            int pointerSize       = _type.Context.Target.PointerSize;
            int minimumObjectSize = pointerSize * 3;
            int objectSize;

            if (_type is MetadataType)
            {
                objectSize = pointerSize +
                             ((MetadataType)_type).InstanceByteCount; // +pointerSize for SyncBlock
            }
            else if (_type is ArrayType)
            {
                objectSize = 3 * pointerSize; // SyncBlock + EETypePtr + Length
                int rank = ((ArrayType)_type).Rank;
                if (rank > 1)
                {
                    objectSize +=
                        2 * _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() * rank;
                }
            }
            else
            {
                throw new NotImplementedException();
            }

            objectSize = AlignmentHelper.AlignUp(objectSize, pointerSize);
            objectSize = Math.Max(minimumObjectSize, objectSize);

            if (_type.IsString)
            {
                // If this is a string, throw away objectSize we computed so far. Strings are special.
                // SyncBlock + EETypePtr + length + firstChar
                objectSize = 2 * pointerSize +
                             _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() +
                             _type.Context.GetWellKnownType(WellKnownType.Char).GetElementSize();
            }

            objData.EmitInt(objectSize);

            if (Type.BaseType != null)
            {
                if (_constructed)
                {
                    objData.EmitPointerReloc(factory.ConstructedTypeSymbol(Type.BaseType));
                }
                else
                {
                    objData.EmitPointerReloc(factory.NecessaryTypeSymbol(Type.BaseType));
                }
            }
            else
            {
                objData.EmitZeroPointer();
            }

            if (_constructed)
            {
                OutputVirtualSlots(ref objData, _type, _type, factory);
            }

            return(objData.ToObjectData());
        }
Exemple #9
0
        protected virtual void OutputBaseSize(ref ObjectDataBuilder objData)
        {
            int pointerSize = _type.Context.Target.PointerSize;
            int objectSize;

            if (_type.IsDefType)
            {
                LayoutInt instanceByteCount = ((DefType)_type).InstanceByteCount;

                if (instanceByteCount.IsIndeterminate)
                {
                    // Some value must be put in, but the specific value doesn't matter as it
                    // isn't used for specific instantiations, and the universal canon eetype
                    // is never associated with an allocated object.
                    objectSize = pointerSize;
                }
                else
                {
                    objectSize = pointerSize +
                                 ((DefType)_type).InstanceByteCount.AsInt; // +pointerSize for SyncBlock
                }

                if (_type.IsValueType)
                {
                    objectSize += pointerSize; // + EETypePtr field inherited from System.Object
                }
            }
            else if (_type.IsArray)
            {
                objectSize = 3 * pointerSize; // SyncBlock + EETypePtr + Length
                if (_type.IsMdArray)
                {
                    objectSize +=
                        2 * sizeof(int) * ((ArrayType)_type).Rank;
                }
            }
            else if (_type.IsPointer)
            {
                // These never get boxed and don't have a base size. Use a sentinel value recognized by the runtime.
                objData.EmitInt(ParameterizedTypeShapeConstants.Pointer);
                return;
            }
            else if (_type.IsByRef)
            {
                // These never get boxed and don't have a base size. Use a sentinel value recognized by the runtime.
                objData.EmitInt(ParameterizedTypeShapeConstants.ByRef);
                return;
            }
            else
            {
                throw new NotImplementedException();
            }

            objectSize = AlignmentHelper.AlignUp(objectSize, pointerSize);
            objectSize = Math.Max(MinimumObjectSize, objectSize);

            if (_type.IsString)
            {
                // If this is a string, throw away objectSize we computed so far. Strings are special.
                // SyncBlock + EETypePtr + length + firstChar
                objectSize = 2 * pointerSize +
                             sizeof(int) +
                             StringComponentSize.Value;
            }

            objData.EmitInt(objectSize);
        }
Exemple #10
0
 private void AlignNextObject(ref ObjectDataBuilder builder, NodeFactory factory)
 {
     builder.EmitZeros(AlignmentHelper.AlignUp(builder.CountBytes, factory.Target.PointerSize) - builder.CountBytes);
 }
Exemple #11
0
    /// <summary>
    /// Creates a new <see cref="Buffer{T}"/> instance with the specified parameters.
    /// </summary>
    /// <param name="device">The <see cref="GraphicsDevice"/> associated with the current instance.</param>
    /// <param name="length">The number of items to store in the current buffer.</param>
    /// <param name="elementSizeInBytes">The size in bytes of each buffer item (including padding, if any).</param>
    /// <param name="resourceType">The resource type for the current buffer.</param>
    /// <param name="allocationMode">The allocation mode to use for the new resource.</param>
    private protected Buffer(GraphicsDevice device, int length, uint elementSizeInBytes, ResourceType resourceType, AllocationMode allocationMode)
    {
        device.ThrowIfDisposed();

        if (resourceType == ResourceType.Constant)
        {
            Guard.IsBetweenOrEqualTo(length, 1, D3D12.D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
        }
        else
        {
            // The maximum length is set such that the aligned buffer size can't exceed uint.MaxValue
            Guard.IsBetweenOrEqualTo(length, 1, (uint.MaxValue / elementSizeInBytes) & ~255);
        }

        if (TypeInfo <T> .IsDoubleOrContainsDoubles &&
            device.D3D12Device->CheckFeatureSupport <D3D12_FEATURE_DATA_D3D12_OPTIONS>(D3D12_FEATURE_D3D12_OPTIONS).DoublePrecisionFloatShaderOps == 0)
        {
            UnsupportedDoubleOperationException.Throw <T>();
        }

        nint usableSizeInBytes    = checked ((nint)(length * elementSizeInBytes));
        nint effectiveSizeInBytes = resourceType == ResourceType.Constant ? AlignmentHelper.Pad(usableSizeInBytes, D3D12.D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT) : usableSizeInBytes;

        SizeInBytes    = usableSizeInBytes;
        GraphicsDevice = device;
        Length         = length;

#if NET6_0_OR_GREATER
        this.allocation    = device.Allocator->CreateResource(device.Pool, resourceType, allocationMode, (ulong)effectiveSizeInBytes);
        this.d3D12Resource = new ComPtr <ID3D12Resource>(this.allocation.Get()->GetResource());
#else
        this.d3D12Resource = device.D3D12Device->CreateCommittedResource(resourceType, (ulong)effectiveSizeInBytes, device.IsCacheCoherentUMA);
#endif

        device.RegisterAllocatedResource();
        device.RentShaderResourceViewDescriptorHandles(out this.d3D12ResourceDescriptorHandles);
        device.RentShaderResourceViewDescriptorHandles(out this.d3D12ResourceDescriptorHandlesForTypedUnorderedAccessView);

        switch (resourceType)
        {
        case ResourceType.Constant:
            device.D3D12Device->CreateConstantBufferView(this.d3D12Resource.Get(), effectiveSizeInBytes, this.d3D12ResourceDescriptorHandles.D3D12CpuDescriptorHandle);
            break;

        case ResourceType.ReadOnly:
            device.D3D12Device->CreateShaderResourceView(this.d3D12Resource.Get(), (uint)length, elementSizeInBytes, this.d3D12ResourceDescriptorHandles.D3D12CpuDescriptorHandle);
            break;

        case ResourceType.ReadWrite:
            device.D3D12Device->CreateUnorderedAccessView(this.d3D12Resource.Get(), (uint)length, elementSizeInBytes, this.d3D12ResourceDescriptorHandles.D3D12CpuDescriptorHandle);
            device.D3D12Device->CreateUnorderedAccessViewForClear(
                this.d3D12Resource.Get(),
                DXGI_FORMAT_R32_UINT,
                (uint)(usableSizeInBytes / sizeof(uint)),
                this.d3D12ResourceDescriptorHandlesForTypedUnorderedAccessView.D3D12CpuDescriptorHandle,
                this.d3D12ResourceDescriptorHandlesForTypedUnorderedAccessView.D3D12CpuDescriptorHandleNonShaderVisible);
            break;
        }

        this.d3D12Resource.Get()->SetName(this);
    }