Нема описа
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

050-TestStructs.cs 53KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. using Burst.Compiler.IL.Tests.Helpers;
  5. using NUnit.Framework;
  6. using Unity.Burst;
  7. using Unity.Collections.LowLevel.Unsafe;
  8. using Unity.Mathematics;
  9. using UnityBenchShared;
  10. namespace Burst.Compiler.IL.Tests
  11. {
  12. internal partial class TestStructs
  13. {
  14. [TestCompiler]
  15. public static float test_struct_func_call_by_value()
  16. {
  17. var localVar = new CustomStruct();
  18. localVar.firstfield = 94;
  19. localVar.value = 123;
  20. return byvalue_function_helper(localVar);
  21. }
  22. [TestCompiler]
  23. public static float test_struct_func_call_by_ref()
  24. {
  25. var localVar = new CustomStruct
  26. {
  27. firstfield = 94,
  28. value = 123
  29. };
  30. byref_function_helper(ref localVar);
  31. return localVar.value;
  32. }
  33. [TestCompiler]
  34. public static float test_struct_func_call_instance()
  35. {
  36. var localVar = new CustomStruct2 { value = 123 };
  37. return localVar.returnDoubleValue();
  38. }
  39. [TestCompiler]
  40. public static float test_struct_constructor_nondefault()
  41. {
  42. var localVar = new CustomStruct2(123.0f);
  43. return localVar.value;
  44. }
  45. [TestCompiler]
  46. public static float test_struct_constructor_default()
  47. {
  48. var localVar = new CustomStruct2();
  49. localVar.value = 1;
  50. return localVar.value;
  51. }
  52. [TestCompiler]
  53. public static float test_struct_copysemantic()
  54. {
  55. var a = new CustomStruct2 { value = 123.0f };
  56. var b = a;
  57. b.value = 345;
  58. return b.value;
  59. }
  60. [TestCompiler]
  61. public static float test_struct_nested()
  62. {
  63. var a = new TestNestedStruct { v1 = { x = 5 } };
  64. return a.v1.x;
  65. }
  66. [TestCompiler(1.0f)]
  67. public static float test_struct_multiple_fields(float x)
  68. {
  69. var v = new TestVector4
  70. {
  71. x = 1.0f,
  72. y = 2.0f,
  73. z = 3.0f,
  74. w = 4.0f
  75. };
  76. return x + v.x + v.y + v.z + v.w;
  77. }
  78. [TestCompiler]
  79. public static float test_struct_multi_assign()
  80. {
  81. var a = new MultiAssignStruct(2.0F);
  82. return a.x + a.y + a.z;
  83. }
  84. [TestCompiler]
  85. public static int test_custom_struct_return_simple()
  86. {
  87. var a = return_value_helper_simple(1, 2);
  88. return a.firstfield + a.value;
  89. }
  90. [TestCompiler]
  91. public static int test_custom_struct_return_constructor()
  92. {
  93. var a = return_value_helper_constructor(1, 2);
  94. return a.firstfield + a.value;
  95. }
  96. [TestCompiler]
  97. public static int test_struct_self_reference()
  98. {
  99. var a = new SelfReferenceStruct
  100. {
  101. Value = 1
  102. };
  103. return a.Value;
  104. }
  105. [TestCompiler]
  106. public static int test_struct_deep()
  107. {
  108. var deep = new DeepStruct2();
  109. deep.value.value.SetValue(10);
  110. return deep.value.value.GetValue() + deep.value.value.value;
  111. }
  112. [TestCompiler(2)]
  113. public static int test_struct_empty(int x)
  114. {
  115. var emptyStruct = new EmptyStruct();
  116. var result = emptyStruct.Increment(x);
  117. return result;
  118. }
  119. [TestCompiler]
  120. public static float test_struct_with_static_fields()
  121. {
  122. StructWithStaticVariables myStruct = new StructWithStaticVariables();
  123. myStruct.myFloat = 5;
  124. myStruct = copy_struct_with_static_by_value(myStruct);
  125. mutate_struct_with_static_by_ref_value(ref myStruct);
  126. return myStruct.myFloat;
  127. }
  128. [TestCompiler(true)]
  129. [TestCompiler(false)]
  130. public static bool TestStructWithBoolAsInt(bool value)
  131. {
  132. var structWithBoolAsInt = new StructWithBoolAsInt(value);
  133. return structWithBoolAsInt;
  134. }
  135. [TestCompiler]
  136. [Ignore("IL Instruction LEAVE not yet supported")]
  137. public static int TestStructDisposable()
  138. {
  139. using (var structDisposable = new StructDisposable())
  140. {
  141. return structDisposable.x + 1;
  142. }
  143. }
  144. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_InstructionStsfldNotSupported)]
  145. public static void TestStructWithStaticFieldWrite()
  146. {
  147. var test = new StructWithStaticField();
  148. test.CheckWrite();
  149. }
  150. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoadingFromNonReadonlyStaticFieldNotSupported)]
  151. public static void TestStructWithStaticFieldRead()
  152. {
  153. var test = new StructWithStaticField();
  154. test.CheckRead();
  155. }
  156. [TestCompiler]
  157. public static int TestExplicitLayoutSize()
  158. {
  159. return UnsafeUtility.SizeOf<Color>();
  160. }
  161. [TestCompiler]
  162. public static int TestExplicitLayoutStruct()
  163. {
  164. var color = new Color() { Value = 0xAABBCCDD };
  165. var a = color.Value + GetColorR(ref color) + GetColorG(color) + color.GetColorB() + color.A;
  166. var pair = new NumberPair()
  167. {
  168. SignedA = -13,
  169. UnsignedB = 37
  170. };
  171. var b = pair.SignedA - ((int)pair.UnsignedA) + pair.SignedB - ((int)pair.UnsignedB);
  172. return ((int)a) + b;
  173. }
  174. static uint GetColorR(ref Color color)
  175. {
  176. return color.R;
  177. }
  178. static uint GetColorG(Color color)
  179. {
  180. return color.G;
  181. }
  182. [TestCompiler]
  183. public static uint TestExplicitLayoutWrite()
  184. {
  185. var color = new Color() { Value = 0xAABBCCDD };
  186. color.G = 3;
  187. ColorWriteBByRef(ref color, 7);
  188. return color.Value;
  189. }
  190. static void ColorWriteBByRef(ref Color color, byte v)
  191. {
  192. color.B = v;
  193. }
  194. [StructLayout(LayoutKind.Explicit)]
  195. private unsafe struct ExplicitLayoutStructUnaligned
  196. {
  197. [FieldOffset(0)] public int a;
  198. [FieldOffset(4)] public sbyte b;
  199. [FieldOffset(5)] public int c;
  200. [FieldOffset(9)] public fixed int d[4];
  201. }
  202. [TestCompiler]
  203. public static unsafe int TestExplicitLayoutStructUnaligned()
  204. {
  205. var value = new ExplicitLayoutStructUnaligned
  206. {
  207. a = -2,
  208. b = -5,
  209. c = 9
  210. };
  211. value.d[0] = 1;
  212. value.d[1] = 2;
  213. value.d[2] = 3;
  214. value.d[3] = 4;
  215. return value.a + value.b + value.c + value.d[0] + value.d[1] + value.d[2] + value.d[3];
  216. }
  217. [StructLayout(LayoutKind.Explicit)]
  218. public unsafe struct ExplicitLayoutStructFixedBuffer
  219. {
  220. [FieldOffset(0)]
  221. public int First;
  222. [FieldOffset(4)]
  223. public fixed int Data[128];
  224. public struct Provider : IArgumentProvider
  225. {
  226. public object Value => new ExplicitLayoutStructFixedBuffer(3);
  227. }
  228. public ExplicitLayoutStructFixedBuffer(int x)
  229. {
  230. First = x;
  231. fixed (int* dataPtr = Data)
  232. {
  233. dataPtr[8] = x + 2;
  234. }
  235. }
  236. }
  237. #if UNITY_ANDROID || UNITY_IOS
  238. [Ignore("This test fails on mobile platforms")]
  239. #endif
  240. [TestCompiler(typeof(ExplicitLayoutStructFixedBuffer.Provider))]
  241. public static unsafe int TestExplicitLayoutStructFixedBuffer(ref ExplicitLayoutStructFixedBuffer x)
  242. {
  243. return x.First + x.Data[8];
  244. }
  245. [StructLayout(LayoutKind.Explicit, Size = 9)]
  246. public struct ExplicitStructWithSize
  247. {
  248. [FieldOffset(0)] public int a;
  249. [FieldOffset(4)] public sbyte b;
  250. [FieldOffset(5)] public int c;
  251. }
  252. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  253. public static unsafe int TestStructSizingExplicitStructWithSize()
  254. {
  255. return UnsafeUtility.SizeOf<ExplicitStructWithSize>();
  256. }
  257. [StructLayout(LayoutKind.Sequential, Size = 9)]
  258. public struct SequentialStructWithSize
  259. {
  260. public int a;
  261. public int b;
  262. public sbyte c;
  263. }
  264. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  265. public static unsafe int TestStructSizingSequentialStructWithSize()
  266. {
  267. return UnsafeUtility.SizeOf<SequentialStructWithSize>();
  268. }
  269. [StructLayout(LayoutKind.Sequential, Size = 13)]
  270. public struct SequentialStructWithSize2
  271. {
  272. public int a;
  273. public int b;
  274. public sbyte c;
  275. }
  276. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  277. public static unsafe int TestStructSizingSequentialStructWithSize2()
  278. {
  279. return UnsafeUtility.SizeOf<SequentialStructWithSize2>();
  280. }
  281. [StructLayout(LayoutKind.Sequential, Size = 12, Pack = 8)]
  282. private struct StructSequentialWithSizeAndPack8
  283. {
  284. public double FieldA;
  285. public int FieldB;
  286. }
  287. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  288. public static unsafe int TestStructSizingSequentialStructWithSizeAndPack8()
  289. {
  290. return UnsafeUtility.SizeOf<StructSequentialWithSizeAndPack8>();
  291. }
  292. [StructLayout(LayoutKind.Explicit, Size = 12, Pack = 8)]
  293. private struct StructExplicitWithSizeAndPack8
  294. {
  295. [FieldOffset(0)]
  296. public double FieldA;
  297. [FieldOffset(8)]
  298. public int FieldB;
  299. }
  300. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  301. public static unsafe int TestStructSizingSequentialStructWithSizeAndPack()
  302. {
  303. return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack8>();
  304. }
  305. private struct StructExplicitWithSizeAndPack8Wrapper
  306. {
  307. public byte FieldA;
  308. public StructExplicitWithSizeAndPack8 FieldB;
  309. }
  310. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  311. public static unsafe int TestStructExplicitWithSizeAndPack8Wrapper()
  312. {
  313. return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack8Wrapper>();
  314. }
  315. [StructLayout(LayoutKind.Sequential, Size = 10)]
  316. private struct StructSequentialWithSizeSmallerThanActual
  317. {
  318. public double FieldA;
  319. public int FieldB;
  320. }
  321. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  322. public static unsafe int TestStructSequentialWithSizeSmallerThanActual()
  323. {
  324. return UnsafeUtility.SizeOf<StructSequentialWithSizeSmallerThanActual>();
  325. }
  326. [StructLayout(LayoutKind.Explicit, Size = 10)]
  327. private struct StructExplicitWithSizeSmallerThanActual
  328. {
  329. [FieldOffset(0)]
  330. public double FieldA;
  331. [FieldOffset(8)]
  332. public int FieldB;
  333. }
  334. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  335. public static unsafe int TestStructExplicitWithSizeSmallerThanActual()
  336. {
  337. return UnsafeUtility.SizeOf<StructExplicitWithSizeSmallerThanActual>();
  338. }
  339. [StructLayout(LayoutKind.Explicit, Size = 12)]
  340. private struct StructExplicitWithSizeAndOverlappingFields
  341. {
  342. [FieldOffset(0)]
  343. public double FieldA;
  344. [FieldOffset(4)]
  345. public int FieldB;
  346. [FieldOffset(8)]
  347. public int FieldC;
  348. }
  349. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  350. public static unsafe int TestStructExplicitWithSizeAndOverlappingFields()
  351. {
  352. return UnsafeUtility.SizeOf<StructExplicitWithSizeAndOverlappingFields>();
  353. }
  354. [StructLayout(LayoutKind.Explicit, Size = 12)]
  355. private struct StructExplicitWithSize
  356. {
  357. [FieldOffset(0)]
  358. public double FieldA;
  359. [FieldOffset(8)]
  360. public int FieldB;
  361. }
  362. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  363. public static unsafe int TestStructExplicitWithSize()
  364. {
  365. return UnsafeUtility.SizeOf<StructExplicitWithSize>();
  366. }
  367. [StructLayout(LayoutKind.Explicit, Size = 17)]
  368. private struct StructExplicitWithSize17
  369. {
  370. [FieldOffset(0)]
  371. public double FieldA;
  372. [FieldOffset(8)]
  373. public int FieldB;
  374. }
  375. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  376. public static unsafe int TestStructExplicitWithSize17()
  377. {
  378. return UnsafeUtility.SizeOf<StructExplicitWithSize17>();
  379. }
  380. [StructLayout(LayoutKind.Explicit)]
  381. public struct ExplicitStructEmpty { }
  382. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  383. public static unsafe int TestStructSizingExplicitStructEmpty()
  384. {
  385. return UnsafeUtility.SizeOf<ExplicitStructEmpty>();
  386. }
  387. public struct ExplicitStructEmptyContainer
  388. {
  389. public ExplicitStructEmpty A;
  390. public int B;
  391. }
  392. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  393. public static unsafe int TestEmptyStructEmbeddedInStruct()
  394. {
  395. return UnsafeUtility.SizeOf<ExplicitStructEmptyContainer>();
  396. }
  397. [StructLayout(LayoutKind.Explicit, Size = 0)]
  398. public struct ExplicitStructEmptyWithSize { }
  399. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  400. public static unsafe int TestStructSizingExplicitStructEmptyWithSize()
  401. {
  402. return UnsafeUtility.SizeOf<ExplicitStructEmptyWithSize>();
  403. }
  404. public struct SequentialStructEmptyNoAttributes { }
  405. [TestCompiler]
  406. public static unsafe int TestStructSizingSequentialStructEmptyNoAttributes()
  407. {
  408. return UnsafeUtility.SizeOf<SequentialStructEmptyNoAttributes>();
  409. }
  410. [StructLayout(LayoutKind.Sequential)]
  411. public struct SequentialStructEmpty { }
  412. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  413. public static unsafe int TestStructSizingSequentialStructEmpty()
  414. {
  415. return UnsafeUtility.SizeOf<SequentialStructEmpty>();
  416. }
  417. [StructLayout(LayoutKind.Sequential, Size = 0)]
  418. public struct SequentialStructEmptyWithSize { }
  419. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  420. public static unsafe int TestStructSizingSequentialStructEmptyWithSize()
  421. {
  422. return UnsafeUtility.SizeOf<SequentialStructEmptyWithSize>();
  423. }
  424. [StructLayout(LayoutKind.Sequential, Size = 1)]
  425. public struct SequentialStructEmptyWithNonZeroSize { }
  426. [TestCompiler]
  427. public static unsafe int TestStructSizingSequentialStructEmptyWithNonZeroSize()
  428. {
  429. return UnsafeUtility.SizeOf<SequentialStructEmptyWithNonZeroSize>();
  430. }
  431. [StructLayout(LayoutKind.Auto)]
  432. public struct AutoStruct
  433. {
  434. public int a;
  435. }
  436. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructWithAutoLayoutNotSupported)]
  437. public static unsafe int TestAutoStruct()
  438. {
  439. return UnsafeUtility.SizeOf<AutoStruct>();
  440. }
  441. [TestCompiler]
  442. public static int TestNestedExplicitLayouts()
  443. {
  444. var nested = new NestedExplicit0()
  445. {
  446. Next = new NestedExplicit1()
  447. {
  448. Next = new NestedExplicit2()
  449. {
  450. FValue = 13.37f
  451. }
  452. }
  453. };
  454. var a = nested.NextAsInt + nested.Next.NextAsInt + nested.Next.Next.IValue;
  455. nested.Next.Next.FValue = 0.0042f;
  456. var b = nested.NextAsInt + nested.Next.NextAsInt + nested.Next.Next.IValue;
  457. return a + b;
  458. }
  459. [TestCompiler]
  460. public static int TestNestedExplicitLayoutsSize()
  461. {
  462. return UnsafeUtility.SizeOf<NestedExplicit0>();
  463. }
  464. [TestCompiler]
  465. public static uint TestBitcast()
  466. {
  467. return new FloatRepr()
  468. {
  469. Value = 13.37f
  470. }.AsUint;
  471. }
  472. [TestCompiler]
  473. public static uint TestExplicitStructFromCall()
  474. {
  475. return ReturnStruct().Value + ReturnStruct().R;
  476. }
  477. static Color ReturnStruct()
  478. {
  479. return new Color()
  480. {
  481. R = 10,
  482. G = 20,
  483. B = 30,
  484. A = 255
  485. };
  486. }
  487. [TestCompiler]
  488. public static unsafe uint TestExplicitLayoutStructWithFixedArray()
  489. {
  490. var x = new FixedArrayExplitLayoutStruct()
  491. {
  492. UpperUInt = 0xAABBCCDD,
  493. LowerUInt = 0xEEFF3344
  494. };
  495. uint sum = 0;
  496. for (int i = 0; i < 8; i++)
  497. {
  498. sum += x.Bytes[i];
  499. if (i < 4) sum += x.Shorts[i];
  500. }
  501. return x.UpperUInt + x.LowerUInt + sum;
  502. }
  503. [TestCompiler]
  504. public static unsafe int TestExplicitLayoutStructWithFixedArraySize()
  505. {
  506. return UnsafeUtility.SizeOf<FixedArrayExplitLayoutStruct>();
  507. }
  508. public struct StructInvalid
  509. {
  510. public string WowThatStringIsNotSupported;
  511. }
  512. //private struct StructInvalidProvider : IArgumentProvider
  513. //{
  514. // public object[] Arguments => new object[] { new StructInvalid() };
  515. //}
  516. private static CustomStruct return_value_helper_simple(int a, int b)
  517. {
  518. CustomStruct val;
  519. val.firstfield = a;
  520. val.value = b;
  521. return val;
  522. }
  523. private static CustomStruct return_value_helper_constructor(int a, int b)
  524. {
  525. return new CustomStruct(a, b);
  526. }
  527. private static float byvalue_function_helper(CustomStruct customStruct)
  528. {
  529. return customStruct.value * 2;
  530. }
  531. private static void byref_function_helper(ref CustomStruct customStruct)
  532. {
  533. customStruct.value = customStruct.value * 2;
  534. }
  535. static StructWithStaticVariables copy_struct_with_static_by_value(StructWithStaticVariables byValue)
  536. {
  537. byValue.myFloat += 2;
  538. return byValue;
  539. }
  540. static void mutate_struct_with_static_by_ref_value(ref StructWithStaticVariables byValue)
  541. {
  542. byValue.myFloat += 2;
  543. }
  544. private struct EmptyStruct
  545. {
  546. public int Increment(int x)
  547. {
  548. return x + 1;
  549. }
  550. }
  551. private struct CustomStruct
  552. {
  553. public int firstfield;
  554. public int value;
  555. public CustomStruct(int a, int b)
  556. {
  557. firstfield = a;
  558. value = b;
  559. }
  560. }
  561. struct DeepStruct2
  562. {
  563. #pragma warning disable 0649
  564. public DeepStruct1 value;
  565. #pragma warning restore 0649
  566. }
  567. struct DeepStruct1
  568. {
  569. #pragma warning disable 0649
  570. public DeepStruct0 value;
  571. #pragma warning restore 0649
  572. }
  573. struct DeepStruct0
  574. {
  575. public int value;
  576. public void SetValue(int value)
  577. {
  578. this.value = value;
  579. }
  580. public int GetValue()
  581. {
  582. return value;
  583. }
  584. }
  585. private struct CustomStruct2
  586. {
  587. public float value;
  588. public float returnDoubleValue()
  589. {
  590. return value;
  591. }
  592. public CustomStruct2(float initialValue)
  593. {
  594. value = initialValue;
  595. }
  596. }
  597. private struct TestVector4
  598. {
  599. public float x;
  600. public float y;
  601. public float z;
  602. public float w;
  603. }
  604. private struct StructWithBoolAsInt
  605. {
  606. private int _value;
  607. public StructWithBoolAsInt(bool value)
  608. {
  609. _value = value ? 1 : 0;
  610. }
  611. public static implicit operator bool(StructWithBoolAsInt val)
  612. {
  613. return val._value != 0;
  614. }
  615. }
  616. private struct TestNestedStruct
  617. {
  618. public TestVector4 v1;
  619. }
  620. private struct MultiAssignStruct
  621. {
  622. public float x;
  623. public float y;
  624. public float z;
  625. public MultiAssignStruct(float val)
  626. {
  627. x = y = z = val;
  628. }
  629. }
  630. private struct SelfReferenceStruct
  631. {
  632. #pragma warning disable 0649
  633. public int Value;
  634. public unsafe SelfReferenceStruct* Left;
  635. public unsafe SelfReferenceStruct* Right;
  636. #pragma warning restore 0649
  637. }
  638. private struct StructForSizeOf
  639. {
  640. #pragma warning disable 0649
  641. public IntPtr Value1;
  642. public Float4 Vec1;
  643. public IntPtr Value2;
  644. public Float4 Vec2;
  645. #pragma warning disable 0649
  646. }
  647. private struct StructWithStaticField
  648. {
  649. public static int MyField;
  650. public void CheckWrite()
  651. {
  652. MyField = 0;
  653. }
  654. public int CheckRead()
  655. {
  656. return MyField;
  657. }
  658. }
  659. private struct Float4
  660. {
  661. #pragma warning disable 0649
  662. public float x;
  663. public float y;
  664. public float z;
  665. public float w;
  666. #pragma warning restore 0649
  667. }
  668. private struct StructWithStaticVariables
  669. {
  670. #pragma warning disable 0414
  671. #pragma warning disable 0649
  672. const float static_const_float = 9;
  673. static string static_string = "hello";
  674. public float myFloat;
  675. public Float4 myFloat4;
  676. static float static_float_2 = 5;
  677. #pragma warning restore 0649
  678. #pragma warning restore 0414
  679. }
  680. struct StructDisposable : IDisposable
  681. {
  682. public int x;
  683. public void Dispose()
  684. {
  685. x++;
  686. }
  687. }
  688. [StructLayout(LayoutKind.Explicit)]
  689. private struct Color
  690. {
  691. [FieldOffset(0)] public uint Value;
  692. [FieldOffset(0)] public byte R;
  693. [FieldOffset(1)] public byte G;
  694. [FieldOffset(2)] public byte B;
  695. [FieldOffset(3)] public byte A;
  696. public byte GetColorB()
  697. {
  698. return B;
  699. }
  700. }
  701. [StructLayout(LayoutKind.Explicit)]
  702. private struct NumberPair
  703. {
  704. [FieldOffset(0)] public uint UnsignedA;
  705. [FieldOffset(0)] public int SignedA;
  706. [FieldOffset(4)] public uint UnsignedB;
  707. [FieldOffset(4)] public int SignedB;
  708. }
  709. [StructLayout(LayoutKind.Explicit)]
  710. private struct NestedExplicit0
  711. {
  712. [FieldOffset(0)] public NestedExplicit1 Next;
  713. [FieldOffset(0)] public int NextAsInt;
  714. }
  715. [StructLayout(LayoutKind.Explicit)]
  716. private struct NestedExplicit1
  717. {
  718. [FieldOffset(0)] public NestedExplicit2 Next;
  719. [FieldOffset(0)] public int NextAsInt;
  720. }
  721. [StructLayout(LayoutKind.Explicit)]
  722. private struct NestedExplicit2
  723. {
  724. [FieldOffset(0)] public float FValue;
  725. [FieldOffset(0)] public int IValue;
  726. }
  727. [StructLayout(LayoutKind.Explicit)]
  728. private struct FloatRepr
  729. {
  730. [FieldOffset(0)] public float Value;
  731. [FieldOffset(0)] public uint AsUint;
  732. }
  733. [StructLayout(LayoutKind.Explicit, Size = 24)]
  734. private struct PaddedStruct
  735. {
  736. [FieldOffset(8)] public int Value;
  737. }
  738. [StructLayout(LayoutKind.Explicit)]
  739. private unsafe struct FixedArrayExplitLayoutStruct
  740. {
  741. [FieldOffset(0)] public fixed byte Bytes[8];
  742. [FieldOffset(0)] public fixed ushort Shorts[4];
  743. [FieldOffset(0)] public uint UpperUInt;
  744. [FieldOffset(4)] public uint LowerUInt;
  745. }
  746. [StructLayout(LayoutKind.Explicit)]
  747. public unsafe struct Chunk
  748. {
  749. [FieldOffset(0)] public Chunk* Archetype;
  750. [FieldOffset(8)] public Chunk* metaChunkEntity;
  751. [FieldOffset(16)] public int Count;
  752. }
  753. [TestCompiler]
  754. public static unsafe int TestRegressionInvalidGetElementPtrStructLayout()
  755. {
  756. Chunk* c = stackalloc Chunk[1];
  757. c[0].Archetype = null;
  758. c[0].metaChunkEntity = null;
  759. c[0].Count = 0;
  760. return TestRegressionInvalidGetElementPtrStructLayoutInternal(0, 1, &c);
  761. }
  762. public static unsafe int TestRegressionInvalidGetElementPtrStructLayoutInternal(int index, int limit, Chunk** currentChunk)
  763. {
  764. int rValue = 0;
  765. while (index >= limit + 1)
  766. {
  767. rValue += (*currentChunk)->Count;
  768. index += 1;
  769. }
  770. return rValue;
  771. }
  772. [StructLayout(LayoutKind.Explicit)]
  773. public unsafe struct Packet
  774. {
  775. [FieldOffset(0)] public int data;
  776. [FieldOffset(0)] public fixed byte moreData[1500];
  777. }
  778. [TestCompiler]
  779. public static unsafe int TestExplicitSizeReporting()
  780. {
  781. return sizeof(Packet);
  782. }
  783. [StructLayout(LayoutKind.Explicit)]
  784. private struct ExplicitStructPackedButWithHoles
  785. {
  786. [FieldOffset(0)]
  787. public byte A;
  788. [FieldOffset(1)]
  789. public long B;
  790. [FieldOffset(21)]
  791. public byte C;
  792. }
  793. [TestCompiler]
  794. public static int TestExplicitStructPackedButWithHolesSize()
  795. {
  796. return UnsafeUtility.SizeOf<ExplicitStructPackedButWithHoles>();
  797. }
  798. [TestCompiler]
  799. public static unsafe int TestExplicitStructPackedButWithHolesOffsetC()
  800. {
  801. var value = new ExplicitStructPackedButWithHoles();
  802. var addressStart = &value;
  803. var addressField = &value.C;
  804. return (int)((byte*)addressField - (byte*)addressStart);
  805. }
  806. private struct ExplicitStructPackedButWithHolesContainer
  807. {
  808. public ExplicitStructPackedButWithHoles A;
  809. public int B;
  810. public ExplicitStructPackedButWithHoles C;
  811. }
  812. [TestCompiler]
  813. public static int TestExplicitStructPackedButWithHolesContainerSize()
  814. {
  815. return UnsafeUtility.SizeOf<ExplicitStructPackedButWithHolesContainer>();
  816. }
  817. [TestCompiler]
  818. public static unsafe int TestExplicitStructPackedButWithHolesContainerOffsetC()
  819. {
  820. var value = new ExplicitStructPackedButWithHolesContainer();
  821. var addressStart = &value;
  822. var addressField = &value.C;
  823. return (int)((byte*)addressField - (byte*)addressStart);
  824. }
  825. [StructLayout(LayoutKind.Explicit)]
  826. private struct ExplicitStructNotPackedWithHoles
  827. {
  828. [FieldOffset(4)]
  829. public int A;
  830. [FieldOffset(12)]
  831. public int B;
  832. }
  833. [TestCompiler]
  834. public static int TestExplicitStructNotPackedWithHolesSize()
  835. {
  836. return UnsafeUtility.SizeOf<ExplicitStructNotPackedWithHoles>();
  837. }
  838. [TestCompiler]
  839. public static float TestExplicitStructNested()
  840. {
  841. StructWithNestUnion b;
  842. b.Value.Min = 5.0f;
  843. return b.Value.Min;
  844. }
  845. [TestCompiler]
  846. public static float TestExplicitStructNestedAsArgument()
  847. {
  848. float Helper(StructWithNestUnion outer)
  849. {
  850. return outer.Value.Min;
  851. }
  852. return Helper(new StructWithNestUnion
  853. {
  854. Value = new UnionValue { Min = 5.0f }
  855. });
  856. }
  857. public struct StructWithNestUnion
  858. {
  859. public UnionValue Value;
  860. }
  861. [StructLayout(LayoutKind.Explicit)]
  862. public struct UnionValue
  863. {
  864. [FieldOffset(0)]
  865. public float Min;
  866. [FieldOffset(4)]
  867. public float Max;
  868. [FieldOffset(0)]
  869. public uint Property;
  870. }
  871. #if UNITY_ANDROID || UNITY_IOS
  872. [Ignore("This test fails on mobile platforms")]
  873. #endif
  874. [TestCompiler(typeof(NetworkEndPoint.Provider), typeof(NetworkEndPoint.Provider), ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructByValueNotSupported)]
  875. public static bool TestABITransformIntoExplicitLayoutTransform(NetworkEndPoint a, NetworkEndPoint b)
  876. {
  877. return a.Compare(b);
  878. }
  879. [StructLayout(LayoutKind.Explicit)]
  880. public unsafe struct NetworkEndPoint
  881. {
  882. internal const int ArrayLength = 2;
  883. [FieldOffset(0)]
  884. internal fixed byte data[ArrayLength];
  885. [FieldOffset(0)]
  886. internal ushort family;
  887. [FieldOffset(28)]
  888. internal int length;
  889. public bool Compare(NetworkEndPoint other)
  890. {
  891. if (length != other.length)
  892. return false;
  893. return true;
  894. }
  895. public class Provider : IArgumentProvider
  896. {
  897. public object Value => default(NetworkEndPoint);
  898. }
  899. }
  900. public struct SequentialStructWithPaddingAndVectorField
  901. {
  902. public byte a;
  903. public float2 b;
  904. public class Provider : IArgumentProvider
  905. {
  906. public object Value => new SequentialStructWithPaddingAndVectorField { a = 1, b = new float2(4, 5) };
  907. }
  908. }
  909. #if UNITY_ANDROID || UNITY_IOS
  910. [Ignore("This test fails on mobile platforms")]
  911. #endif
  912. [TestCompiler(typeof(SequentialStructWithPaddingAndVectorField.Provider))]
  913. public static int TestSequentialStructWithPaddingAndVectorField(ref SequentialStructWithPaddingAndVectorField value)
  914. {
  915. return (int)value.b.x;
  916. }
  917. private static void TestSequentialStructWithPaddingAndVectorFieldRefHelper(ref SequentialStructWithPaddingAndVectorField value)
  918. {
  919. value.b.yx = value.b;
  920. value.b = value.b.yx;
  921. }
  922. #if UNITY_ANDROID || UNITY_IOS
  923. [Ignore("This test fails on mobile platforms")]
  924. #endif
  925. [TestCompiler(typeof(SequentialStructWithPaddingAndVectorField.Provider))]
  926. public static int TestSequentialStructWithPaddingAndVectorFieldRef(ref SequentialStructWithPaddingAndVectorField value)
  927. {
  928. TestSequentialStructWithPaddingAndVectorFieldRefHelper(ref value);
  929. return (int)value.b.x;
  930. }
  931. [TestCompiler]
  932. public static unsafe int TestSequentialStructWithPaddingAndVectorFieldPtr()
  933. {
  934. var vec = new float2(1, 2);
  935. var vecPtr = &vec;
  936. var value = new SequentialStructWithPaddingAndVectorField();
  937. value.b = *vecPtr;
  938. return (int)value.b.x;
  939. }
  940. [TestCompiler]
  941. public static unsafe int TestCreatingVectorTypeFromNonVectorScalarType()
  942. {
  943. var x = (short)4;
  944. var value = new int4(x, x, x, x);
  945. return value.w;
  946. }
  947. [StructLayout(LayoutKind.Explicit)]
  948. public struct ExplicitVectors
  949. {
  950. [FieldOffset(0)]
  951. public int A;
  952. [FieldOffset(4)]
  953. public int2 B; //NB: Any Vector type is sufficient
  954. }
  955. [TestCompiler]
  956. public static unsafe int TestVectorLoadFromExplicitStruct()
  957. {
  958. var header = new ExplicitVectors { };
  959. return header.B.x;
  960. }
  961. [TestCompiler(DataRange.Standard)]
  962. public static unsafe int TestVectorStoreToExplicitStruct(ref int2 a)
  963. {
  964. var header = new ExplicitVectors { B = a };
  965. return header.B.x;
  966. }
  967. [TestCompiler(typeof(StructWithNonBlittableTypes), ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotBlittableForFunctionPointer)]
  968. public static unsafe int TestStructWithNonBlittableTypes(ref StructWithNonBlittableTypes a)
  969. {
  970. var checksum = 0;
  971. checksum = (checksum * 397) ^ a.a0;
  972. checksum = (checksum * 397) ^ a.b0;
  973. checksum = (checksum * 397) ^ a.b1;
  974. checksum = (checksum * 397) ^ (a.d0 ? 10 : 0);
  975. checksum = (checksum * 397) ^ a.a1;
  976. checksum = (checksum * 397) ^ a.b1;
  977. checksum = (checksum * 397) ^ a.c1;
  978. checksum = (checksum * 397) ^ (a.d1 ? 0 : 7);
  979. checksum = (checksum * 397) ^ a.Check;
  980. return checksum;
  981. }
  982. [TestCompiler(typeof(StructWithNonBlittableTypesWithMarshalAs))]
  983. public static unsafe int TestStructWithBlittableTypesWithMarshalAs(ref StructWithNonBlittableTypesWithMarshalAs a)
  984. {
  985. var checksum = 0;
  986. checksum = (checksum * 397) ^ a.a0;
  987. checksum = (checksum * 397) ^ a.b0;
  988. checksum = (checksum * 397) ^ a.b1;
  989. checksum = (checksum * 397) ^ (a.d0 ? 10 : 0);
  990. checksum = (checksum * 397) ^ a.a1;
  991. checksum = (checksum * 397) ^ a.b1;
  992. checksum = (checksum * 397) ^ a.c1;
  993. checksum = (checksum * 397) ^ (a.d1 ? 0 : 7);
  994. checksum = (checksum * 397) ^ a.Check;
  995. return checksum;
  996. }
  997. [TestCompiler]
  998. public static int TestSizeOfStructWithBlittableTypesWithMarshalAs()
  999. {
  1000. return UnsafeUtility.SizeOf<StructWithNonBlittableTypesWithMarshalAs>();
  1001. }
  1002. #if BURST_TESTS_ONLY
  1003. [TestCompiler(typeof(StructWithNonBlittableTypes), ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotBlittableForFunctionPointer)]
  1004. public static int TestStructWithNonBlittableTypesOffset(ref StructWithNonBlittableTypes a)
  1005. {
  1006. return Unsafe.ByteOffset(ref a.a0, ref a.a1).ToInt32();
  1007. }
  1008. #endif
  1009. [TestCompiler(typeof(StructWithBlittableTypes))]
  1010. public static unsafe int TestStructWithBlittableTypes(ref StructWithBlittableTypes a)
  1011. {
  1012. var checksum = 0;
  1013. checksum = (checksum * 397) ^ a.a;
  1014. checksum = (checksum * 397) ^ a.b;
  1015. checksum = (checksum * 397) ^ a.c;
  1016. checksum = (checksum * 397) ^ a.d.x;
  1017. checksum = (checksum * 397) ^ a.d.y;
  1018. return checksum;
  1019. }
  1020. [TestCompiler]
  1021. public static int TestStructWithPointerDependency()
  1022. {
  1023. var test = new StructWithPointerDependency();
  1024. return test.DirectNoDependency.Value;
  1025. }
  1026. [TestCompiler]
  1027. public static uint TestExplicitStructNestedFieldAccess()
  1028. {
  1029. var buffer = new StructWithNestUnionContainer();
  1030. return buffer.Something.Value.Property;
  1031. }
  1032. public struct StructWithNestUnionContainer
  1033. {
  1034. public StructWithNestUnion Something => new StructWithNestUnion { Value = new UnionValue { Property = 42 } };
  1035. }
  1036. public struct StructWithBlittableTypes : IArgumentProvider
  1037. {
  1038. public StructWithBlittableTypes(int a, int b, int c, int2 d)
  1039. {
  1040. this.a = a;
  1041. this.b = b;
  1042. this.c = c;
  1043. this.d = d;
  1044. }
  1045. public int a;
  1046. public int b;
  1047. public int c;
  1048. public int2 d;
  1049. public object Value => new StructWithBlittableTypes(1, 2, 3, new int2(4, 5));
  1050. }
  1051. public struct StructWithNonBlittableTypes : IArgumentProvider
  1052. {
  1053. public StructWithNonBlittableTypes(byte a0, byte b0, byte c0, bool d0, byte a1, byte b1, byte c1, bool d1, int check)
  1054. {
  1055. this.a0 = a0;
  1056. this.b0 = b0;
  1057. this.c0 = c0;
  1058. this.d0 = d0;
  1059. this.a1 = a1;
  1060. this.b1 = b1;
  1061. this.c1 = c1;
  1062. this.d1 = d1;
  1063. this.Check = check;
  1064. }
  1065. public byte a0;
  1066. public byte b0;
  1067. public byte c0;
  1068. public bool d0;
  1069. public byte a1;
  1070. public byte b1;
  1071. public byte c1;
  1072. public bool d1;
  1073. public int Check;
  1074. public object Value => new StructWithNonBlittableTypes(1, 2, 3, true, 5, 6, 7, false, 0x12345678);
  1075. }
  1076. public struct StructWithNonBlittableTypesWithMarshalAs : IArgumentProvider
  1077. {
  1078. public StructWithNonBlittableTypesWithMarshalAs(byte a0, byte b0, byte c0, bool d0, byte a1, byte b1, byte c1, bool d1, int check)
  1079. {
  1080. this.a0 = a0;
  1081. this.b0 = b0;
  1082. this.c0 = c0;
  1083. this.d0 = d0;
  1084. this.a1 = a1;
  1085. this.b1 = b1;
  1086. this.c1 = c1;
  1087. this.d1 = d1;
  1088. this.Check = check;
  1089. }
  1090. public byte a0;
  1091. public byte b0;
  1092. public byte c0;
  1093. [MarshalAs(UnmanagedType.U1)]
  1094. public bool d0;
  1095. public byte a1;
  1096. public byte b1;
  1097. public byte c1;
  1098. [MarshalAs(UnmanagedType.U1)]
  1099. public bool d1;
  1100. public int Check;
  1101. public object Value => new StructWithNonBlittableTypesWithMarshalAs(1, 2, 3, true, 5, 6, 7, false, 0x12345678);
  1102. }
  1103. public unsafe struct StructWithPointerDependency
  1104. {
  1105. public StructWithNoDependency* PointerToNoDependency;
  1106. public StructWithNoDependency DirectNoDependency;
  1107. }
  1108. public struct StructWithNoDependency
  1109. {
  1110. public int Value;
  1111. }
  1112. [StructLayout(LayoutKind.Sequential, Size = 4096)]
  1113. public unsafe struct Sized4096
  1114. {
  1115. public byte First;
  1116. public struct Provider : IArgumentProvider
  1117. {
  1118. public object Value => new Sized4096();
  1119. }
  1120. }
  1121. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1122. public static unsafe void TestSized4096(ref Sized4096 a, ref Sized4096 b)
  1123. {
  1124. a = b;
  1125. }
  1126. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1127. public static unsafe void TestSized4096ManualCopy(ref Sized4096 a, ref Sized4096 b)
  1128. {
  1129. for (int i = 0; i < UnsafeUtility.SizeOf<Sized4096>(); i++)
  1130. {
  1131. fixed (byte* aBytes = &a.First, bBytes = &b.First)
  1132. {
  1133. aBytes[i] = bBytes[i];
  1134. }
  1135. }
  1136. }
  1137. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1138. public static unsafe void TestSized4096CopyToAlloca(ref Sized4096 a, ref Sized4096 b)
  1139. {
  1140. Sized4096 c = b;
  1141. (&c.First)[4] = 42;
  1142. a = c;
  1143. }
  1144. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1145. public static unsafe void TestSized4096CopyToStackAlloc0(ref Sized4096 a, ref Sized4096 b)
  1146. {
  1147. Sized4096* c = stackalloc Sized4096[1];
  1148. (&c->First)[4] = 42;
  1149. a = *c;
  1150. }
  1151. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1152. public static unsafe void TestSized4096CopyToStackAlloc1(ref Sized4096 a, ref Sized4096 b)
  1153. {
  1154. byte* bytes = stackalloc byte[4096];
  1155. Sized4096* c = (Sized4096*)bytes;
  1156. (&c->First)[4] = 42;
  1157. a = *c;
  1158. }
  1159. [StructLayout(LayoutKind.Sequential, Size = 4096)]
  1160. public struct MultipleSized4096
  1161. {
  1162. public Sized4096 a;
  1163. public Sized4096 b;
  1164. public struct Provider : IArgumentProvider
  1165. {
  1166. public object Value => new MultipleSized4096 { a = new Sized4096(), b = new Sized4096() };
  1167. }
  1168. }
  1169. [TestCompiler(typeof(MultipleSized4096.Provider), typeof(Sized4096.Provider))]
  1170. public static void TestMultipleSized4096(ref MultipleSized4096 a, ref Sized4096 b)
  1171. {
  1172. a.a = b;
  1173. a.a.First = 42;
  1174. b = a.b;
  1175. }
  1176. [TestCompiler(typeof(MultipleSized4096.Provider), typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1177. public static void TestMultipleSized4096CopyToAlloca(ref MultipleSized4096 a, ref Sized4096 b, ref Sized4096 c)
  1178. {
  1179. MultipleSized4096 d = default;
  1180. d.a = b;
  1181. b = d.b;
  1182. c = a.a;
  1183. a = d;
  1184. }
  1185. public unsafe struct Fixed4096
  1186. {
  1187. public fixed byte First[4096];
  1188. public struct Provider : IArgumentProvider
  1189. {
  1190. public object Value => new Fixed4096();
  1191. }
  1192. }
  1193. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1194. public static unsafe void TestFixed4096(ref Fixed4096 a, ref Fixed4096 b)
  1195. {
  1196. a = b;
  1197. }
  1198. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1199. public static unsafe void TestFixed4096ManualCopy(ref Fixed4096 a, ref Fixed4096 b)
  1200. {
  1201. for (int i = 0; i < UnsafeUtility.SizeOf<Fixed4096>(); i++)
  1202. {
  1203. a.First[i] = b.First[i];
  1204. }
  1205. }
  1206. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1207. public static unsafe void TestFixed4096CopyToAlloca(ref Fixed4096 a, ref Fixed4096 b)
  1208. {
  1209. Fixed4096 c = b;
  1210. c.First[4] = 42;
  1211. a = c;
  1212. }
  1213. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1214. public static unsafe void TestFixed4096CopyToStackAlloc0(ref Fixed4096 a, ref Fixed4096 b)
  1215. {
  1216. Fixed4096* c = stackalloc Fixed4096[1];
  1217. c->First[4] = 42;
  1218. a = *c;
  1219. }
  1220. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1221. public static unsafe void TestFixed4096CopyToStackAlloc1(ref Fixed4096 a, ref Fixed4096 b)
  1222. {
  1223. byte* bytes = stackalloc byte[4096];
  1224. Fixed4096* c = (Fixed4096*)bytes;
  1225. c->First[4] = 42;
  1226. a = *c;
  1227. }
  1228. public unsafe struct PointersInStruct
  1229. {
  1230. public byte* a;
  1231. public byte* b;
  1232. public struct Provider : IArgumentProvider
  1233. {
  1234. public object Value => new PointersInStruct { a = null, b = null };
  1235. }
  1236. }
  1237. [TestCompiler(typeof(PointersInStruct.Provider), typeof(Fixed4096.Provider))]
  1238. public static unsafe void TestPointersInStruct(ref PointersInStruct a, ref Fixed4096 b)
  1239. {
  1240. fixed (byte* ptr = b.First)
  1241. {
  1242. a.a = ptr;
  1243. }
  1244. a.b = a.a;
  1245. }
  1246. private static unsafe T GenericGetT<T>(T* t) where T : unmanaged
  1247. {
  1248. return *t;
  1249. }
  1250. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1251. public static unsafe void TestGetStructThroughGeneric(ref Fixed4096 a, ref Fixed4096 b)
  1252. {
  1253. fixed (void* ptr = &a)
  1254. {
  1255. var elem = GenericGetT<Fixed4096>((Fixed4096*) ptr);
  1256. b = elem;
  1257. }
  1258. }
  1259. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1260. public static unsafe void TestGetStructThroughReadArrayElement(ref Fixed4096 a, ref Fixed4096 b)
  1261. {
  1262. fixed (void* ptr = &a)
  1263. {
  1264. var elem = UnsafeUtility.ReadArrayElement<Fixed4096>(ptr, 0);
  1265. b = elem;
  1266. }
  1267. }
  1268. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1269. public static unsafe void TestSetStructThroughWriteArrayElement(ref Fixed4096 a, ref Fixed4096 b)
  1270. {
  1271. fixed (void* ptr = &a)
  1272. {
  1273. var elem = a;
  1274. UnsafeUtility.WriteArrayElement(ptr, 0, elem);
  1275. }
  1276. }
  1277. private struct Fixed1021
  1278. {
  1279. public unsafe fixed byte Data[1021];
  1280. }
  1281. [TestCompiler(typeof(Fixed4096.Provider))]
  1282. public static unsafe void TestGetSetStructThroughReadWriteArrayElement(ref Fixed4096 a)
  1283. {
  1284. fixed (void* ptr1 = &a)
  1285. {
  1286. var ptr2 = (byte*) ptr1 + 1;
  1287. UnsafeUtility.WriteArrayElement(ptr1, 0, UnsafeUtility.ReadArrayElement<Fixed1021>(ptr2, 0));
  1288. }
  1289. }
  1290. [TestCompiler(typeof(Fixed4096.Provider))]
  1291. public static unsafe void TestGetSetStructThroughReadWriteArrayElementNoAlias(ref Fixed4096 a)
  1292. {
  1293. fixed (void* ptr1 = &a)
  1294. {
  1295. var ptr2 = (byte*) ptr1 + UnsafeUtility.SizeOf<Fixed1021>();
  1296. UnsafeUtility.WriteArrayElement(ptr1, 0, UnsafeUtility.ReadArrayElement<Fixed1021>(ptr2, 0));
  1297. }
  1298. }
  1299. [StructLayout(LayoutKind.Sequential, Size = 2)]
  1300. public struct WithPadding
  1301. {
  1302. public byte A;
  1303. public struct Provider : IArgumentProvider
  1304. {
  1305. public object Value => new WithPadding { A = 42 };
  1306. }
  1307. }
  1308. private static readonly WithPadding withPadding = new WithPadding { A = 42 };
  1309. [TestCompiler(typeof(ReturnBox))]
  1310. public static unsafe byte TestWithPadding(WithPadding* o)
  1311. {
  1312. *o = withPadding;
  1313. return withPadding.A;
  1314. }
  1315. [CompilerGenerated]
  1316. [StructLayout(LayoutKind.Sequential)]
  1317. public unsafe struct MyCompilerGeneratedButNotReally
  1318. {
  1319. public fixed int A[1];
  1320. }
  1321. private static readonly MyCompilerGeneratedButNotReally myCompilerGeneratedButNotReally = new MyCompilerGeneratedButNotReally { };
  1322. [TestCompiler(typeof(ReturnBox))]
  1323. public static unsafe int TestMyCompilerGeneratedButNotReallyStruct(MyCompilerGeneratedButNotReally* o)
  1324. {
  1325. *o = myCompilerGeneratedButNotReally;
  1326. fixed (int* a = myCompilerGeneratedButNotReally.A)
  1327. {
  1328. return *a;
  1329. }
  1330. }
  1331. public unsafe struct UninitFieldsAreZero
  1332. {
  1333. public fixed ushort a[3];
  1334. public fixed byte b[3];
  1335. public UninitFieldsAreZero(ushort x, ushort y, ushort z)
  1336. {
  1337. a[0] = x;
  1338. a[1] = y;
  1339. a[2] = z;
  1340. }
  1341. }
  1342. [TestCompiler(typeof(ReturnBox))]
  1343. public static unsafe void TestUninitFieldsAreZero(UninitFieldsAreZero* o)
  1344. {
  1345. o->a[0] = 42;
  1346. o->a[1] = 42;
  1347. o->a[2] = 42;
  1348. o->b[0] = 42;
  1349. o->b[1] = 42;
  1350. o->b[2] = 42;
  1351. var n = new UninitFieldsAreZero(13, 53, 4);
  1352. *o = n;
  1353. }
  1354. #pragma warning disable 0649
  1355. private struct ExplicitSizesMatchB
  1356. {
  1357. public uint U;
  1358. }
  1359. private struct ExplicitSizesMatchC
  1360. {
  1361. public ulong L;
  1362. public uint U;
  1363. public ushort S;
  1364. public byte B;
  1365. }
  1366. [StructLayout(LayoutKind.Explicit)]
  1367. private struct ExplicitSizesMatch
  1368. {
  1369. [FieldOffset(0)] public int A;
  1370. [FieldOffset(4)] public ExplicitSizesMatchB B;
  1371. [FieldOffset(4)] public ExplicitSizesMatchC C;
  1372. }
  1373. #pragma warning restore 0649
  1374. [TestCompiler]
  1375. public static unsafe int TestExplicitSizesMatch()
  1376. {
  1377. return sizeof(ExplicitSizesMatch);
  1378. }
  1379. #if BURST_TESTS_ONLY
  1380. private struct ExplicitLayoutAndBoolStruct
  1381. {
  1382. [StructLayout(LayoutKind.Explicit)]
  1383. public struct ExplicitLayoutStruct
  1384. {
  1385. [FieldOffset(0)]
  1386. public byte Byte;
  1387. }
  1388. // Having `bool` AND a field whose type is an explicit-layout struct
  1389. // causes .NET to fallback to auto-layout for the containing struct.
  1390. public bool Bool;
  1391. public ExplicitLayoutStruct ExplicitLayout;
  1392. public long Int64;
  1393. }
  1394. // This test just exists to verify that .NET does indeed do the fallback
  1395. // to auto-layout that we expect it does, since this is the underlying
  1396. // reason for us to prevent the combination of
  1397. // "bool + explicit-layout struct".
  1398. [Test]
  1399. [WindowsOnly(".NET falls back to auto-layout for this struct, but Mono doesn't")]
  1400. public static unsafe void TestExplicitLayoutAndBoolCausesDotNetToFallbackToAutoLayout()
  1401. {
  1402. var s = new ExplicitLayoutAndBoolStruct();
  1403. var offsetStart = (IntPtr)(&s);
  1404. var offsetField = (IntPtr)(&s.Int64);
  1405. var offset = offsetField.ToInt64() - offsetStart.ToInt64();
  1406. // We would expect the offset to the `Int64` field to be 8.
  1407. // But because .NET falls back to auto-layout,
  1408. // and places the `Int64` field first,
  1409. // the offset is actually 0.
  1410. Assert.AreEqual((long)0, offset);
  1411. }
  1412. [TestCompiler(EnableAutoLayoutFallbackCheck = true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_NonBlittableAndNonManagedSequentialStructNotSupported)]
  1413. public static long TestExplicitLayoutAndBoolIsNotSupported()
  1414. {
  1415. return new ExplicitLayoutAndBoolStruct { Int64 = 8 }.Int64;
  1416. }
  1417. private struct ExplicitLayoutNestedAndBoolStruct
  1418. {
  1419. public struct SequentialLayoutStruct
  1420. {
  1421. #pragma warning disable 0649
  1422. public ExplicitLayoutStruct ExplicitLayout;
  1423. #pragma warning restore 0649
  1424. }
  1425. [StructLayout(LayoutKind.Explicit)]
  1426. public struct ExplicitLayoutStruct
  1427. {
  1428. [FieldOffset(0)]
  1429. public byte Byte;
  1430. }
  1431. #pragma warning disable 0649
  1432. public bool Bool;
  1433. public SequentialLayoutStruct SequentialLayout;
  1434. #pragma warning restore 0649
  1435. public long Int64;
  1436. }
  1437. [TestCompiler(EnableAutoLayoutFallbackCheck = true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_NonBlittableAndNonManagedSequentialStructNotSupported)]
  1438. public static long TestExplicitLayoutNestedAndBoolIsNotSupported()
  1439. {
  1440. return new ExplicitLayoutNestedAndBoolStruct { Int64 = 8 }.Int64;
  1441. }
  1442. private struct ExplicitLayoutStructAndBoolWithMarshalAs
  1443. {
  1444. [StructLayout(LayoutKind.Explicit)]
  1445. public struct ExplicitLayoutStruct
  1446. {
  1447. [FieldOffset(0)]
  1448. public byte Byte;
  1449. }
  1450. #pragma warning disable 0649
  1451. [MarshalAs(UnmanagedType.U1)]
  1452. public bool Bool;
  1453. public ExplicitLayoutStruct ExplicitLayout;
  1454. #pragma warning restore 0649
  1455. public long Int64;
  1456. }
  1457. [TestCompiler(EnableAutoLayoutFallbackCheck = true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_NonBlittableAndNonManagedSequentialStructNotSupported)]
  1458. public static unsafe long TestExplicitLayoutAndBoolWithMarshalAsIsNotSupported()
  1459. {
  1460. return new ExplicitLayoutStructAndBoolWithMarshalAs { Int64 = 8 }.Int64;
  1461. }
  1462. #endif
  1463. private struct SequentialLayoutAndBoolStruct
  1464. {
  1465. public struct SequentialLayoutStruct
  1466. {
  1467. #pragma warning disable 0649
  1468. public byte Byte;
  1469. #pragma warning restore 0649
  1470. }
  1471. #pragma warning disable 0649
  1472. public bool Bool;
  1473. public SequentialLayoutStruct SequentialLayout;
  1474. #pragma warning restore 0649
  1475. public long Int64;
  1476. }
  1477. [TestCompiler]
  1478. public static unsafe long TestSequentialLayoutAndBoolIsSupported()
  1479. {
  1480. return new SequentialLayoutAndBoolStruct { Int64 = 8 }.Int64;
  1481. }
  1482. }
  1483. }