| File: Compiler\RuntimeConfigurationRootProvider.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Text; using ILCompiler.DependencyAnalysis; using Internal.Text; namespace ILCompiler { /// <summary> /// A root provider that provides a runtime configuration blob that influences runtime behaviors. /// See RhConfigValues.h for allowed values. /// </summary> public class RuntimeConfigurationRootProvider : ICompilationRootProvider { private readonly string _blobName; private readonly IReadOnlyCollection<string> _runtimeOptions; public RuntimeConfigurationRootProvider(string blobName, IReadOnlyCollection<string> runtimeOptions) { _blobName = blobName; _runtimeOptions = runtimeOptions; } void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) { rootProvider.AddCompilationRoot(new RuntimeConfigurationBlobNode(_blobName, _runtimeOptions), "Runtime configuration"); } private sealed class RuntimeConfigurationBlobNode : ObjectNode, ISymbolDefinitionNode { private readonly string _blobName; private readonly IReadOnlyCollection<string> _runtimeOptions; public RuntimeConfigurationBlobNode(string blobName, IReadOnlyCollection<string> runtimeOptions) { _blobName = blobName; _runtimeOptions = runtimeOptions; } public int Offset => 0; public override bool IsShareable => false; public override int ClassCode => 7864454; public override bool StaticDependenciesAreComputed => true; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.NodeMangler.ExternVariable(new Utf8String(_blobName))); } public override ObjectNodeSection GetSection(NodeFactory factory) => factory.Target.IsWindows ? ObjectNodeSection.ReadOnlyDataSection : ObjectNodeSection.DataSection; protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { var builder = new ObjectDataBuilder(factory.TypeSystemContext.Target, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); var settings = new Dictionary<string, ISymbolNode>(); // Put values in a dictionary - we expect many "true" strings, for example. var valueDict = new Dictionary<string, ISymbolNode>(); int valueIndex = 0; foreach (string line in _runtimeOptions) { int indexOfEquals = line.IndexOf('='); if (indexOfEquals > 0) { string key = line.Substring(0, indexOfEquals); string value = line.Substring(indexOfEquals + 1); if (!valueDict.TryGetValue(value, out ISymbolNode valueNode)) { valueNode = factory.ReadOnlyDataBlob( new Utf8String(_blobName + "_value_" + valueIndex++), Utf8NullTerminatedBytes(value), alignment: 1); valueDict.Add(value, valueNode); } settings[key] = valueNode; } } // The format is: // * Number of entries (T) // * N times pointer to key // * N times pointer to value builder.EmitNaturalInt(settings.Count); int i = 0; foreach (string key in settings.Keys) { ISymbolNode node = factory.ReadOnlyDataBlob( new Utf8String(_blobName + "_key_" + i++), Utf8NullTerminatedBytes(key), alignment: 1); builder.EmitPointerReloc(node); } foreach (ISymbolNode value in settings.Values) { builder.EmitPointerReloc(value); } static byte[] Utf8NullTerminatedBytes(string s) { byte[] result = new byte[Encoding.UTF8.GetByteCount(s) + 1]; Encoding.UTF8.GetBytes(s, result); return result; } return builder.ToObjectData(); } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { return _blobName.CompareTo(((RuntimeConfigurationBlobNode)other)._blobName); } } } }