1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using Debug = System.Diagnostics.Debug; 7 8 namespace Internal.TypeSystem 9 { 10 /// <summary> 11 /// Specifies the target CPU architecture. 12 /// </summary> 13 public enum TargetArchitecture 14 { 15 Unknown, 16 ARM, 17 ARMEL, 18 ARM64, 19 X64, 20 X86, 21 Wasm32 22 } 23 24 /// <summary> 25 /// Specifies the target ABI. 26 /// </summary> 27 public enum TargetOS 28 { 29 Unknown, 30 Windows, 31 Linux, 32 OSX, 33 FreeBSD, 34 NetBSD, 35 WebAssembly, 36 } 37 38 public enum TargetAbi 39 { 40 Unknown, 41 /// <summary> 42 /// Cross-platform console model 43 /// </summary> 44 CoreRT, 45 /// <summary> 46 /// Windows-specific UWP model 47 /// </summary> 48 ProjectN, 49 /// <summary> 50 /// Jit runtime ABI 51 /// </summary> 52 Jit 53 } 54 55 /// <summary> 56 /// Represents various details about the compilation target that affect 57 /// layout, padding, allocations, or ABI. 58 /// </summary> 59 public partial class TargetDetails 60 { 61 /// <summary> 62 /// Gets the target CPU architecture. 63 /// </summary> 64 public TargetArchitecture Architecture 65 { 66 get; 67 } 68 69 /// <summary> 70 /// Gets the target ABI. 71 /// </summary> 72 public TargetOS OperatingSystem 73 { 74 get; 75 } 76 77 public TargetAbi Abi 78 { 79 get; 80 } 81 82 /// <summary> 83 /// Gets the size of a pointer for the target of the compilation. 84 /// </summary> 85 public int PointerSize 86 { 87 get 88 { 89 switch (Architecture) 90 { 91 case TargetArchitecture.ARM64: 92 case TargetArchitecture.X64: 93 return 8; 94 case TargetArchitecture.ARM: 95 case TargetArchitecture.ARMEL: 96 case TargetArchitecture.X86: 97 case TargetArchitecture.Wasm32: 98 return 4; 99 default: 100 throw new NotSupportedException(); 101 } 102 } 103 } 104 105 /// <summary> 106 /// Gets the maximum alignment to which something can be aligned 107 /// </summary> 108 public static int MaximumAlignment 109 { 110 get 111 { 112 return 8; 113 } 114 } 115 116 public LayoutInt LayoutPointerSize => new LayoutInt(PointerSize); 117 118 /// <summary> 119 /// Gets the default field packing size. 120 /// </summary> 121 public int DefaultPackingSize 122 { 123 get 124 { 125 // We use default packing size of 8 irrespective of the platform. 126 return 8; 127 } 128 } 129 130 /// <summary> 131 /// Gets the minimum required method alignment. 132 /// </summary> 133 public int MinimumFunctionAlignment 134 { 135 get 136 { 137 // We use a minimum alignment of 4 irrespective of the platform. 138 return 4; 139 } 140 } 141 TargetDetails(TargetArchitecture architecture, TargetOS targetOS, TargetAbi abi)142 public TargetDetails(TargetArchitecture architecture, TargetOS targetOS, TargetAbi abi) 143 { 144 Architecture = architecture; 145 OperatingSystem = targetOS; 146 Abi = abi; 147 } 148 149 /// <summary> 150 /// Retrieves the size of a well known type. 151 /// </summary> GetWellKnownTypeSize(DefType type)152 public LayoutInt GetWellKnownTypeSize(DefType type) 153 { 154 switch (type.Category) 155 { 156 case TypeFlags.Void: 157 return new LayoutInt(PointerSize); 158 case TypeFlags.Boolean: 159 return new LayoutInt(1); 160 case TypeFlags.Char: 161 return new LayoutInt(2); 162 case TypeFlags.Byte: 163 case TypeFlags.SByte: 164 return new LayoutInt(1); 165 case TypeFlags.UInt16: 166 case TypeFlags.Int16: 167 return new LayoutInt(2); 168 case TypeFlags.UInt32: 169 case TypeFlags.Int32: 170 return new LayoutInt(4); 171 case TypeFlags.UInt64: 172 case TypeFlags.Int64: 173 return new LayoutInt(8); 174 case TypeFlags.Single: 175 return new LayoutInt(4); 176 case TypeFlags.Double: 177 return new LayoutInt(8); 178 case TypeFlags.UIntPtr: 179 case TypeFlags.IntPtr: 180 return new LayoutInt(PointerSize); 181 } 182 183 // Add new well known types if necessary 184 185 throw new InvalidOperationException(); 186 } 187 188 /// <summary> 189 /// Retrieves the alignment required by a well known type. 190 /// </summary> GetWellKnownTypeAlignment(DefType type)191 public LayoutInt GetWellKnownTypeAlignment(DefType type) 192 { 193 // Size == Alignment for all platforms. 194 return GetWellKnownTypeSize(type); 195 } 196 197 /// <summary> 198 /// Given an alignment of the fields of a type, determine the alignment that is necessary for allocating the object on the GC heap 199 /// </summary> 200 /// <returns></returns> GetObjectAlignment(LayoutInt fieldAlignment)201 public LayoutInt GetObjectAlignment(LayoutInt fieldAlignment) 202 { 203 switch (Architecture) 204 { 205 case TargetArchitecture.ARM: 206 case TargetArchitecture.ARMEL: 207 case TargetArchitecture.Wasm32: 208 // ARM supports two alignments for objects on the GC heap (4 byte and 8 byte) 209 if (fieldAlignment.IsIndeterminate) 210 return LayoutInt.Indeterminate; 211 212 if (fieldAlignment.AsInt <= 4) 213 return new LayoutInt(4); 214 else 215 return new LayoutInt(8); 216 case TargetArchitecture.X64: 217 case TargetArchitecture.ARM64: 218 return new LayoutInt(8); 219 case TargetArchitecture.X86: 220 return new LayoutInt(4); 221 default: 222 throw new NotSupportedException(); 223 } 224 } 225 226 /// <summary> 227 /// Returns True if compiling for Windows 228 /// </summary> 229 public bool IsWindows 230 { 231 get 232 { 233 return OperatingSystem == TargetOS.Windows; 234 } 235 } 236 237 /// <summary> 238 /// Maximum number of elements in a HFA type. 239 /// </summary> 240 public int MaximumHfaElementCount 241 { 242 get 243 { 244 // There is a hard limit of 4 elements on an HFA type, see 245 // http://blogs.msdn.com/b/vcblog/archive/2013/07/12/introducing-vector-calling-convention.aspx 246 Debug.Assert(Architecture == TargetArchitecture.ARM || 247 Architecture == TargetArchitecture.ARMEL || 248 Architecture == TargetArchitecture.ARM64 || 249 Architecture == TargetArchitecture.X64 || 250 Architecture == TargetArchitecture.X86); 251 252 return 4; 253 } 254 } 255 } 256 } 257