暫無描述
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 55KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781
  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 TestStructSizingExplicitStructWithSizeAndPack8()
  302. {
  303. return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack8>();
  304. }
  305. private struct StructExplicitWithSizeAndPack8Wrapper
  306. {
  307. public byte FieldA;
  308. public StructExplicitWithSizeAndPack8 FieldB;
  309. public StructExplicitWithSizeAndPack8Wrapper(byte a, StructExplicitWithSizeAndPack8 b)
  310. {
  311. FieldA = a;
  312. FieldB = b;
  313. }
  314. }
  315. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  316. public static unsafe int TestStructExplicitWithSizeAndPack8Wrapper()
  317. {
  318. return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack8Wrapper>();
  319. }
  320. [StructLayout(LayoutKind.Sequential, Size = 10)]
  321. private struct StructSequentialWithSizeSmallerThanActual
  322. {
  323. public double FieldA;
  324. public int FieldB;
  325. }
  326. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  327. public static unsafe int TestStructSequentialWithSizeSmallerThanActual()
  328. {
  329. return UnsafeUtility.SizeOf<StructSequentialWithSizeSmallerThanActual>();
  330. }
  331. [StructLayout(LayoutKind.Sequential, Size = 12)]
  332. private struct StructSequentialWithSizeSmallerThanNatural
  333. {
  334. public double FieldA;
  335. public int FieldB;
  336. }
  337. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  338. public static unsafe int TestStructSequentialWithSizeSmallerThanNatural()
  339. {
  340. return UnsafeUtility.SizeOf<StructSequentialWithSizeSmallerThanNatural>();
  341. }
  342. [StructLayout(LayoutKind.Explicit, Size = 10)]
  343. private struct StructExplicitWithSizeSmallerThanActual
  344. {
  345. [FieldOffset(0)]
  346. public double FieldA;
  347. [FieldOffset(8)]
  348. public int FieldB;
  349. }
  350. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  351. public static unsafe int TestStructExplicitWithSizeSmallerThanActual()
  352. {
  353. return UnsafeUtility.SizeOf<StructExplicitWithSizeSmallerThanActual>();
  354. }
  355. [StructLayout(LayoutKind.Explicit, Size = 12)]
  356. private struct StructExplicitWithSizeAndOverlappingFields
  357. {
  358. [FieldOffset(0)]
  359. public double FieldA;
  360. [FieldOffset(4)]
  361. public int FieldB;
  362. [FieldOffset(8)]
  363. public int FieldC;
  364. }
  365. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  366. public static unsafe int TestStructExplicitWithSizeAndOverlappingFields()
  367. {
  368. return UnsafeUtility.SizeOf<StructExplicitWithSizeAndOverlappingFields>();
  369. }
  370. [StructLayout(LayoutKind.Explicit, Size = 12)]
  371. private struct StructExplicitWithSize
  372. {
  373. [FieldOffset(0)]
  374. public double FieldA;
  375. [FieldOffset(8)]
  376. public int FieldB;
  377. }
  378. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  379. public static unsafe int TestStructExplicitWithSize()
  380. {
  381. return UnsafeUtility.SizeOf<StructExplicitWithSize>();
  382. }
  383. [StructLayout(LayoutKind.Explicit, Size = 17)]
  384. private struct StructExplicitWithSize17
  385. {
  386. [FieldOffset(0)]
  387. public double FieldA;
  388. [FieldOffset(8)]
  389. public int FieldB;
  390. }
  391. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructSizeNotSupported)]
  392. public static unsafe int TestStructExplicitWithSize17()
  393. {
  394. return UnsafeUtility.SizeOf<StructExplicitWithSize17>();
  395. }
  396. [StructLayout(LayoutKind.Explicit)]
  397. public struct ExplicitStructEmpty { }
  398. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  399. public static unsafe int TestStructSizingExplicitStructEmpty()
  400. {
  401. return UnsafeUtility.SizeOf<ExplicitStructEmpty>();
  402. }
  403. public struct ExplicitStructEmptyContainer
  404. {
  405. public ExplicitStructEmpty A;
  406. public int B;
  407. }
  408. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  409. public static unsafe int TestEmptyStructEmbeddedInStruct()
  410. {
  411. return UnsafeUtility.SizeOf<ExplicitStructEmptyContainer>();
  412. }
  413. [StructLayout(LayoutKind.Explicit, Size = 0)]
  414. public struct ExplicitStructEmptyWithSize { }
  415. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  416. public static unsafe int TestStructSizingExplicitStructEmptyWithSize()
  417. {
  418. return UnsafeUtility.SizeOf<ExplicitStructEmptyWithSize>();
  419. }
  420. public struct SequentialStructEmptyNoAttributes { }
  421. [TestCompiler]
  422. public static unsafe int TestStructSizingSequentialStructEmptyNoAttributes()
  423. {
  424. return UnsafeUtility.SizeOf<SequentialStructEmptyNoAttributes>();
  425. }
  426. [StructLayout(LayoutKind.Sequential)]
  427. public struct SequentialStructEmpty { }
  428. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  429. public static unsafe int TestStructSizingSequentialStructEmpty()
  430. {
  431. return UnsafeUtility.SizeOf<SequentialStructEmpty>();
  432. }
  433. [StructLayout(LayoutKind.Sequential, Size = 0)]
  434. public struct SequentialStructEmptyWithSize { }
  435. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructZeroSizeNotSupported)]
  436. public static unsafe int TestStructSizingSequentialStructEmptyWithSize()
  437. {
  438. return UnsafeUtility.SizeOf<SequentialStructEmptyWithSize>();
  439. }
  440. [StructLayout(LayoutKind.Sequential, Size = 1)]
  441. public struct SequentialStructEmptyWithNonZeroSize { }
  442. [TestCompiler]
  443. public static unsafe int TestStructSizingSequentialStructEmptyWithNonZeroSize()
  444. {
  445. return UnsafeUtility.SizeOf<SequentialStructEmptyWithNonZeroSize>();
  446. }
  447. [StructLayout(LayoutKind.Auto)]
  448. public struct AutoStruct
  449. {
  450. public int a;
  451. }
  452. [TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructWithAutoLayoutNotSupported)]
  453. public static unsafe int TestAutoStruct()
  454. {
  455. return UnsafeUtility.SizeOf<AutoStruct>();
  456. }
  457. [TestCompiler]
  458. public static int TestNestedExplicitLayouts()
  459. {
  460. var nested = new NestedExplicit0()
  461. {
  462. Next = new NestedExplicit1()
  463. {
  464. Next = new NestedExplicit2()
  465. {
  466. FValue = 13.37f
  467. }
  468. }
  469. };
  470. var a = nested.NextAsInt + nested.Next.NextAsInt + nested.Next.Next.IValue;
  471. nested.Next.Next.FValue = 0.0042f;
  472. var b = nested.NextAsInt + nested.Next.NextAsInt + nested.Next.Next.IValue;
  473. return a + b;
  474. }
  475. [TestCompiler]
  476. public static int TestNestedExplicitLayoutsSize()
  477. {
  478. return UnsafeUtility.SizeOf<NestedExplicit0>();
  479. }
  480. [TestCompiler]
  481. public static uint TestBitcast()
  482. {
  483. return new FloatRepr()
  484. {
  485. Value = 13.37f
  486. }.AsUint;
  487. }
  488. [TestCompiler]
  489. public static uint TestExplicitStructFromCall()
  490. {
  491. return ReturnStruct().Value + ReturnStruct().R;
  492. }
  493. static Color ReturnStruct()
  494. {
  495. return new Color()
  496. {
  497. R = 10,
  498. G = 20,
  499. B = 30,
  500. A = 255
  501. };
  502. }
  503. [TestCompiler]
  504. public static unsafe uint TestExplicitLayoutStructWithFixedArray()
  505. {
  506. var x = new FixedArrayExplitLayoutStruct()
  507. {
  508. UpperUInt = 0xAABBCCDD,
  509. LowerUInt = 0xEEFF3344
  510. };
  511. uint sum = 0;
  512. for (int i = 0; i < 8; i++)
  513. {
  514. sum += x.Bytes[i];
  515. if (i < 4) sum += x.Shorts[i];
  516. }
  517. return x.UpperUInt + x.LowerUInt + sum;
  518. }
  519. [TestCompiler]
  520. public static unsafe int TestExplicitLayoutStructWithFixedArraySize()
  521. {
  522. return UnsafeUtility.SizeOf<FixedArrayExplitLayoutStruct>();
  523. }
  524. public struct StructInvalid
  525. {
  526. public string WowThatStringIsNotSupported;
  527. }
  528. //private struct StructInvalidProvider : IArgumentProvider
  529. //{
  530. // public object[] Arguments => new object[] { new StructInvalid() };
  531. //}
  532. private static CustomStruct return_value_helper_simple(int a, int b)
  533. {
  534. CustomStruct val;
  535. val.firstfield = a;
  536. val.value = b;
  537. return val;
  538. }
  539. private static CustomStruct return_value_helper_constructor(int a, int b)
  540. {
  541. return new CustomStruct(a, b);
  542. }
  543. private static float byvalue_function_helper(CustomStruct customStruct)
  544. {
  545. return customStruct.value * 2;
  546. }
  547. private static void byref_function_helper(ref CustomStruct customStruct)
  548. {
  549. customStruct.value = customStruct.value * 2;
  550. }
  551. static StructWithStaticVariables copy_struct_with_static_by_value(StructWithStaticVariables byValue)
  552. {
  553. byValue.myFloat += 2;
  554. return byValue;
  555. }
  556. static void mutate_struct_with_static_by_ref_value(ref StructWithStaticVariables byValue)
  557. {
  558. byValue.myFloat += 2;
  559. }
  560. private struct EmptyStruct
  561. {
  562. public int Increment(int x)
  563. {
  564. return x + 1;
  565. }
  566. }
  567. private struct CustomStruct
  568. {
  569. public int firstfield;
  570. public int value;
  571. public CustomStruct(int a, int b)
  572. {
  573. firstfield = a;
  574. value = b;
  575. }
  576. }
  577. struct DeepStruct2
  578. {
  579. #pragma warning disable 0649
  580. public DeepStruct1 value;
  581. #pragma warning restore 0649
  582. }
  583. struct DeepStruct1
  584. {
  585. #pragma warning disable 0649
  586. public DeepStruct0 value;
  587. #pragma warning restore 0649
  588. }
  589. struct DeepStruct0
  590. {
  591. public int value;
  592. public void SetValue(int value)
  593. {
  594. this.value = value;
  595. }
  596. public int GetValue()
  597. {
  598. return value;
  599. }
  600. }
  601. private struct CustomStruct2
  602. {
  603. public float value;
  604. public float returnDoubleValue()
  605. {
  606. return value;
  607. }
  608. public CustomStruct2(float initialValue)
  609. {
  610. value = initialValue;
  611. }
  612. }
  613. private struct TestVector4
  614. {
  615. public float x;
  616. public float y;
  617. public float z;
  618. public float w;
  619. }
  620. private struct StructWithBoolAsInt
  621. {
  622. private int _value;
  623. public StructWithBoolAsInt(bool value)
  624. {
  625. _value = value ? 1 : 0;
  626. }
  627. public static implicit operator bool(StructWithBoolAsInt val)
  628. {
  629. return val._value != 0;
  630. }
  631. }
  632. private struct TestNestedStruct
  633. {
  634. public TestVector4 v1;
  635. }
  636. private struct MultiAssignStruct
  637. {
  638. public float x;
  639. public float y;
  640. public float z;
  641. public MultiAssignStruct(float val)
  642. {
  643. x = y = z = val;
  644. }
  645. }
  646. private struct SelfReferenceStruct
  647. {
  648. #pragma warning disable 0649
  649. public int Value;
  650. public unsafe SelfReferenceStruct* Left;
  651. public unsafe SelfReferenceStruct* Right;
  652. #pragma warning restore 0649
  653. }
  654. private struct StructForSizeOf
  655. {
  656. #pragma warning disable 0649
  657. public IntPtr Value1;
  658. public Float4 Vec1;
  659. public IntPtr Value2;
  660. public Float4 Vec2;
  661. #pragma warning disable 0649
  662. }
  663. private struct StructWithStaticField
  664. {
  665. public static int MyField;
  666. public void CheckWrite()
  667. {
  668. MyField = 0;
  669. }
  670. public int CheckRead()
  671. {
  672. return MyField;
  673. }
  674. }
  675. private struct Float4
  676. {
  677. #pragma warning disable 0649
  678. public float x;
  679. public float y;
  680. public float z;
  681. public float w;
  682. #pragma warning restore 0649
  683. }
  684. private struct StructWithStaticVariables
  685. {
  686. #pragma warning disable 0414
  687. #pragma warning disable 0649
  688. const float static_const_float = 9;
  689. static string static_string = "hello";
  690. public float myFloat;
  691. public Float4 myFloat4;
  692. static float static_float_2 = 5;
  693. #pragma warning restore 0649
  694. #pragma warning restore 0414
  695. }
  696. struct StructDisposable : IDisposable
  697. {
  698. public int x;
  699. public void Dispose()
  700. {
  701. x++;
  702. }
  703. }
  704. [StructLayout(LayoutKind.Explicit)]
  705. private struct Color
  706. {
  707. [FieldOffset(0)] public uint Value;
  708. [FieldOffset(0)] public byte R;
  709. [FieldOffset(1)] public byte G;
  710. [FieldOffset(2)] public byte B;
  711. [FieldOffset(3)] public byte A;
  712. public byte GetColorB()
  713. {
  714. return B;
  715. }
  716. }
  717. [StructLayout(LayoutKind.Explicit)]
  718. private struct NumberPair
  719. {
  720. [FieldOffset(0)] public uint UnsignedA;
  721. [FieldOffset(0)] public int SignedA;
  722. [FieldOffset(4)] public uint UnsignedB;
  723. [FieldOffset(4)] public int SignedB;
  724. }
  725. [StructLayout(LayoutKind.Explicit)]
  726. private struct NestedExplicit0
  727. {
  728. [FieldOffset(0)] public NestedExplicit1 Next;
  729. [FieldOffset(0)] public int NextAsInt;
  730. }
  731. [StructLayout(LayoutKind.Explicit)]
  732. private struct NestedExplicit1
  733. {
  734. [FieldOffset(0)] public NestedExplicit2 Next;
  735. [FieldOffset(0)] public int NextAsInt;
  736. }
  737. [StructLayout(LayoutKind.Explicit)]
  738. private struct NestedExplicit2
  739. {
  740. [FieldOffset(0)] public float FValue;
  741. [FieldOffset(0)] public int IValue;
  742. }
  743. [StructLayout(LayoutKind.Explicit)]
  744. private struct FloatRepr
  745. {
  746. [FieldOffset(0)] public float Value;
  747. [FieldOffset(0)] public uint AsUint;
  748. }
  749. [StructLayout(LayoutKind.Explicit, Size = 24)]
  750. private struct PaddedStruct
  751. {
  752. [FieldOffset(8)] public int Value;
  753. }
  754. [StructLayout(LayoutKind.Explicit)]
  755. private unsafe struct FixedArrayExplitLayoutStruct
  756. {
  757. [FieldOffset(0)] public fixed byte Bytes[8];
  758. [FieldOffset(0)] public fixed ushort Shorts[4];
  759. [FieldOffset(0)] public uint UpperUInt;
  760. [FieldOffset(4)] public uint LowerUInt;
  761. }
  762. [StructLayout(LayoutKind.Explicit)]
  763. public unsafe struct Chunk
  764. {
  765. [FieldOffset(0)] public Chunk* Archetype;
  766. [FieldOffset(8)] public Chunk* metaChunkEntity;
  767. [FieldOffset(16)] public int Count;
  768. }
  769. [TestCompiler]
  770. public static unsafe int TestRegressionInvalidGetElementPtrStructLayout()
  771. {
  772. Chunk* c = stackalloc Chunk[1];
  773. c[0].Archetype = null;
  774. c[0].metaChunkEntity = null;
  775. c[0].Count = 0;
  776. return TestRegressionInvalidGetElementPtrStructLayoutInternal(0, 1, &c);
  777. }
  778. public static unsafe int TestRegressionInvalidGetElementPtrStructLayoutInternal(int index, int limit, Chunk** currentChunk)
  779. {
  780. int rValue = 0;
  781. while (index >= limit + 1)
  782. {
  783. rValue += (*currentChunk)->Count;
  784. index += 1;
  785. }
  786. return rValue;
  787. }
  788. [StructLayout(LayoutKind.Explicit)]
  789. public unsafe struct Packet
  790. {
  791. [FieldOffset(0)] public int data;
  792. [FieldOffset(0)] public fixed byte moreData[1500];
  793. }
  794. [TestCompiler]
  795. public static unsafe int TestExplicitSizeReporting()
  796. {
  797. return sizeof(Packet);
  798. }
  799. [StructLayout(LayoutKind.Explicit)]
  800. private struct ExplicitStructPackedButWithHoles
  801. {
  802. [FieldOffset(0)]
  803. public byte A;
  804. [FieldOffset(1)]
  805. public long B;
  806. [FieldOffset(21)]
  807. public byte C;
  808. }
  809. [TestCompiler]
  810. public static int TestExplicitStructPackedButWithHolesSize()
  811. {
  812. return UnsafeUtility.SizeOf<ExplicitStructPackedButWithHoles>();
  813. }
  814. [TestCompiler]
  815. public static unsafe int TestExplicitStructPackedButWithHolesOffsetC()
  816. {
  817. var value = new ExplicitStructPackedButWithHoles();
  818. var addressStart = &value;
  819. var addressField = &value.C;
  820. return (int)((byte*)addressField - (byte*)addressStart);
  821. }
  822. private struct ExplicitStructPackedButWithHolesContainer
  823. {
  824. public ExplicitStructPackedButWithHoles A;
  825. public int B;
  826. public ExplicitStructPackedButWithHoles C;
  827. }
  828. [TestCompiler]
  829. public static int TestExplicitStructPackedButWithHolesContainerSize()
  830. {
  831. return UnsafeUtility.SizeOf<ExplicitStructPackedButWithHolesContainer>();
  832. }
  833. [TestCompiler]
  834. public static unsafe int TestExplicitStructPackedButWithHolesContainerOffsetC()
  835. {
  836. var value = new ExplicitStructPackedButWithHolesContainer();
  837. var addressStart = &value;
  838. var addressField = &value.C;
  839. return (int)((byte*)addressField - (byte*)addressStart);
  840. }
  841. [StructLayout(LayoutKind.Explicit)]
  842. private struct ExplicitStructNotPackedWithHoles
  843. {
  844. [FieldOffset(4)]
  845. public int A;
  846. [FieldOffset(12)]
  847. public int B;
  848. }
  849. [TestCompiler]
  850. public static int TestExplicitStructNotPackedWithHolesSize()
  851. {
  852. return UnsafeUtility.SizeOf<ExplicitStructNotPackedWithHoles>();
  853. }
  854. [TestCompiler]
  855. public static float TestExplicitStructNested()
  856. {
  857. StructWithNestUnion b;
  858. b.Value.Min = 5.0f;
  859. return b.Value.Min;
  860. }
  861. [TestCompiler]
  862. public static float TestExplicitStructNestedAsArgument()
  863. {
  864. float Helper(StructWithNestUnion outer)
  865. {
  866. return outer.Value.Min;
  867. }
  868. return Helper(new StructWithNestUnion
  869. {
  870. Value = new UnionValue { Min = 5.0f }
  871. });
  872. }
  873. public struct StructWithNestUnion
  874. {
  875. public UnionValue Value;
  876. }
  877. [StructLayout(LayoutKind.Explicit)]
  878. public struct UnionValue
  879. {
  880. [FieldOffset(0)]
  881. public float Min;
  882. [FieldOffset(4)]
  883. public float Max;
  884. [FieldOffset(0)]
  885. public uint Property;
  886. }
  887. #if UNITY_ANDROID || UNITY_IOS
  888. [Ignore("This test fails on mobile platforms")]
  889. #endif
  890. [TestCompiler(typeof(NetworkEndPoint.Provider), typeof(NetworkEndPoint.Provider), ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_StructByValueNotSupported)]
  891. public static bool TestABITransformIntoExplicitLayoutTransform(NetworkEndPoint a, NetworkEndPoint b)
  892. {
  893. return a.Compare(b);
  894. }
  895. [StructLayout(LayoutKind.Explicit)]
  896. public unsafe struct NetworkEndPoint
  897. {
  898. internal const int ArrayLength = 2;
  899. [FieldOffset(0)]
  900. internal fixed byte data[ArrayLength];
  901. [FieldOffset(0)]
  902. internal ushort family;
  903. [FieldOffset(28)]
  904. internal int length;
  905. public bool Compare(NetworkEndPoint other)
  906. {
  907. if (length != other.length)
  908. return false;
  909. return true;
  910. }
  911. public class Provider : IArgumentProvider
  912. {
  913. public object Value => default(NetworkEndPoint);
  914. }
  915. }
  916. public struct SequentialStructWithPaddingAndVectorField
  917. {
  918. public byte a;
  919. public float2 b;
  920. public class Provider : IArgumentProvider
  921. {
  922. public object Value => new SequentialStructWithPaddingAndVectorField { a = 1, b = new float2(4, 5) };
  923. }
  924. }
  925. #if UNITY_ANDROID || UNITY_IOS
  926. [Ignore("This test fails on mobile platforms")]
  927. #endif
  928. [TestCompiler(typeof(SequentialStructWithPaddingAndVectorField.Provider))]
  929. public static int TestSequentialStructWithPaddingAndVectorField(ref SequentialStructWithPaddingAndVectorField value)
  930. {
  931. return (int)value.b.x;
  932. }
  933. private static void TestSequentialStructWithPaddingAndVectorFieldRefHelper(ref SequentialStructWithPaddingAndVectorField value)
  934. {
  935. value.b.yx = value.b;
  936. value.b = value.b.yx;
  937. }
  938. #if UNITY_ANDROID || UNITY_IOS
  939. [Ignore("This test fails on mobile platforms")]
  940. #endif
  941. [TestCompiler(typeof(SequentialStructWithPaddingAndVectorField.Provider))]
  942. public static int TestSequentialStructWithPaddingAndVectorFieldRef(ref SequentialStructWithPaddingAndVectorField value)
  943. {
  944. TestSequentialStructWithPaddingAndVectorFieldRefHelper(ref value);
  945. return (int)value.b.x;
  946. }
  947. [TestCompiler]
  948. public static unsafe int TestSequentialStructWithPaddingAndVectorFieldPtr()
  949. {
  950. var vec = new float2(1, 2);
  951. var vecPtr = &vec;
  952. var value = new SequentialStructWithPaddingAndVectorField();
  953. value.b = *vecPtr;
  954. return (int)value.b.x;
  955. }
  956. [TestCompiler]
  957. public static unsafe int TestCreatingVectorTypeFromNonVectorScalarType()
  958. {
  959. var x = (short)4;
  960. var value = new int4(x, x, x, x);
  961. return value.w;
  962. }
  963. [StructLayout(LayoutKind.Explicit)]
  964. public struct ExplicitVectors
  965. {
  966. [FieldOffset(0)]
  967. public int A;
  968. [FieldOffset(4)]
  969. public int2 B; //NB: Any Vector type is sufficient
  970. }
  971. [TestCompiler]
  972. public static unsafe int TestVectorLoadFromExplicitStruct()
  973. {
  974. var header = new ExplicitVectors { };
  975. return header.B.x;
  976. }
  977. [TestCompiler(DataRange.Standard)]
  978. public static unsafe int TestVectorStoreToExplicitStruct(ref int2 a)
  979. {
  980. var header = new ExplicitVectors { B = a };
  981. return header.B.x;
  982. }
  983. [TestCompiler(typeof(StructWithNonBlittableTypes), ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotBlittableForFunctionPointer)]
  984. public static unsafe int TestStructWithNonBlittableTypes(ref StructWithNonBlittableTypes a)
  985. {
  986. var checksum = 0;
  987. checksum = (checksum * 397) ^ a.a0;
  988. checksum = (checksum * 397) ^ a.b0;
  989. checksum = (checksum * 397) ^ a.b1;
  990. checksum = (checksum * 397) ^ (a.d0 ? 10 : 0);
  991. checksum = (checksum * 397) ^ a.a1;
  992. checksum = (checksum * 397) ^ a.b1;
  993. checksum = (checksum * 397) ^ a.c1;
  994. checksum = (checksum * 397) ^ (a.d1 ? 0 : 7);
  995. checksum = (checksum * 397) ^ a.Check;
  996. return checksum;
  997. }
  998. [TestCompiler(typeof(StructWithNonBlittableTypesWithMarshalAs))]
  999. public static unsafe int TestStructWithBlittableTypesWithMarshalAs(ref StructWithNonBlittableTypesWithMarshalAs a)
  1000. {
  1001. var checksum = 0;
  1002. checksum = (checksum * 397) ^ a.a0;
  1003. checksum = (checksum * 397) ^ a.b0;
  1004. checksum = (checksum * 397) ^ a.b1;
  1005. checksum = (checksum * 397) ^ (a.d0 ? 10 : 0);
  1006. checksum = (checksum * 397) ^ a.a1;
  1007. checksum = (checksum * 397) ^ a.b1;
  1008. checksum = (checksum * 397) ^ a.c1;
  1009. checksum = (checksum * 397) ^ (a.d1 ? 0 : 7);
  1010. checksum = (checksum * 397) ^ a.Check;
  1011. return checksum;
  1012. }
  1013. [TestCompiler]
  1014. public static int TestSizeOfStructWithBlittableTypesWithMarshalAs()
  1015. {
  1016. return UnsafeUtility.SizeOf<StructWithNonBlittableTypesWithMarshalAs>();
  1017. }
  1018. #if BURST_TESTS_ONLY
  1019. /* Unsafe.ByteOffset - Disabled in net core 7 due to :
  1020. Framework Net 7
  1021. IL_0000: ldarg.1 IL_0000: newobj System.Void System.PlatformNotSupportedException::.ctor()
  1022. IL_0001: ldarg.0 IL_0005: throw args(IL_0000(newobj))
  1023. IL_0002: sub args(IL_0000(ldarg.1), IL_0001(ldarg.0))
  1024. IL_0003: ret args(IL_0002(sub))
  1025. */
  1026. [TestCompiler(typeof(StructWithNonBlittableTypes), ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotBlittableForFunctionPointer,
  1027. IgnoreOnNetCore = true)]
  1028. public static int TestStructWithNonBlittableTypesOffset(ref StructWithNonBlittableTypes a)
  1029. {
  1030. return Unsafe.ByteOffset(ref a.a0, ref a.a1).ToInt32();
  1031. }
  1032. #endif
  1033. [TestCompiler(typeof(StructWithBlittableTypes))]
  1034. public static unsafe int TestStructWithBlittableTypes(ref StructWithBlittableTypes a)
  1035. {
  1036. var checksum = 0;
  1037. checksum = (checksum * 397) ^ a.a;
  1038. checksum = (checksum * 397) ^ a.b;
  1039. checksum = (checksum * 397) ^ a.c;
  1040. checksum = (checksum * 397) ^ a.d.x;
  1041. checksum = (checksum * 397) ^ a.d.y;
  1042. return checksum;
  1043. }
  1044. [TestCompiler]
  1045. public static int TestStructWithPointerDependency()
  1046. {
  1047. var test = new StructWithPointerDependency();
  1048. return test.DirectNoDependency.Value;
  1049. }
  1050. [TestCompiler]
  1051. public static uint TestExplicitStructNestedFieldAccess()
  1052. {
  1053. var buffer = new StructWithNestUnionContainer();
  1054. return buffer.Something.Value.Property;
  1055. }
  1056. public struct StructWithNestUnionContainer
  1057. {
  1058. public StructWithNestUnion Something => new StructWithNestUnion { Value = new UnionValue { Property = 42 } };
  1059. }
  1060. public struct StructWithBlittableTypes : IArgumentProvider
  1061. {
  1062. public StructWithBlittableTypes(int a, int b, int c, int2 d)
  1063. {
  1064. this.a = a;
  1065. this.b = b;
  1066. this.c = c;
  1067. this.d = d;
  1068. }
  1069. public int a;
  1070. public int b;
  1071. public int c;
  1072. public int2 d;
  1073. public object Value => new StructWithBlittableTypes(1, 2, 3, new int2(4, 5));
  1074. }
  1075. public struct StructWithNonBlittableTypes : IArgumentProvider
  1076. {
  1077. public StructWithNonBlittableTypes(byte a0, byte b0, byte c0, bool d0, byte a1, byte b1, byte c1, bool d1, int check)
  1078. {
  1079. this.a0 = a0;
  1080. this.b0 = b0;
  1081. this.c0 = c0;
  1082. this.d0 = d0;
  1083. this.a1 = a1;
  1084. this.b1 = b1;
  1085. this.c1 = c1;
  1086. this.d1 = d1;
  1087. this.Check = check;
  1088. }
  1089. public byte a0;
  1090. public byte b0;
  1091. public byte c0;
  1092. public bool d0;
  1093. public byte a1;
  1094. public byte b1;
  1095. public byte c1;
  1096. public bool d1;
  1097. public int Check;
  1098. public object Value => new StructWithNonBlittableTypes(1, 2, 3, true, 5, 6, 7, false, 0x12345678);
  1099. }
  1100. public struct StructWithNonBlittableTypesWithMarshalAs : IArgumentProvider
  1101. {
  1102. public StructWithNonBlittableTypesWithMarshalAs(byte a0, byte b0, byte c0, bool d0, byte a1, byte b1, byte c1, bool d1, int check)
  1103. {
  1104. this.a0 = a0;
  1105. this.b0 = b0;
  1106. this.c0 = c0;
  1107. this.d0 = d0;
  1108. this.a1 = a1;
  1109. this.b1 = b1;
  1110. this.c1 = c1;
  1111. this.d1 = d1;
  1112. this.Check = check;
  1113. }
  1114. public byte a0;
  1115. public byte b0;
  1116. public byte c0;
  1117. [MarshalAs(UnmanagedType.U1)]
  1118. public bool d0;
  1119. public byte a1;
  1120. public byte b1;
  1121. public byte c1;
  1122. [MarshalAs(UnmanagedType.U1)]
  1123. public bool d1;
  1124. public int Check;
  1125. public object Value => new StructWithNonBlittableTypesWithMarshalAs(1, 2, 3, true, 5, 6, 7, false, 0x12345678);
  1126. }
  1127. public unsafe struct StructWithPointerDependency
  1128. {
  1129. public StructWithNoDependency* PointerToNoDependency;
  1130. public StructWithNoDependency DirectNoDependency;
  1131. }
  1132. public struct StructWithNoDependency
  1133. {
  1134. public int Value;
  1135. }
  1136. [StructLayout(LayoutKind.Sequential, Size = 4096)]
  1137. public unsafe struct Sized4096
  1138. {
  1139. public byte First;
  1140. public struct Provider : IArgumentProvider
  1141. {
  1142. public object Value => new Sized4096();
  1143. }
  1144. }
  1145. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1146. public static unsafe void TestSized4096(ref Sized4096 a, ref Sized4096 b)
  1147. {
  1148. a = b;
  1149. }
  1150. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1151. public static unsafe void TestSized4096ManualCopy(ref Sized4096 a, ref Sized4096 b)
  1152. {
  1153. for (int i = 0; i < UnsafeUtility.SizeOf<Sized4096>(); i++)
  1154. {
  1155. fixed (byte* aBytes = &a.First, bBytes = &b.First)
  1156. {
  1157. aBytes[i] = bBytes[i];
  1158. }
  1159. }
  1160. }
  1161. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1162. public static unsafe void TestSized4096CopyToAlloca(ref Sized4096 a, ref Sized4096 b)
  1163. {
  1164. Sized4096 c = b;
  1165. (&c.First)[4] = 42;
  1166. a = c;
  1167. }
  1168. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1169. public static unsafe void TestSized4096CopyToStackAlloc0(ref Sized4096 a, ref Sized4096 b)
  1170. {
  1171. Sized4096* c = stackalloc Sized4096[1];
  1172. (&c->First)[4] = 42;
  1173. a = *c;
  1174. }
  1175. [TestCompiler(typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1176. public static unsafe void TestSized4096CopyToStackAlloc1(ref Sized4096 a, ref Sized4096 b)
  1177. {
  1178. byte* bytes = stackalloc byte[4096];
  1179. Sized4096* c = (Sized4096*)bytes;
  1180. (&c->First)[4] = 42;
  1181. a = *c;
  1182. }
  1183. [StructLayout(LayoutKind.Sequential, Size = 4096)]
  1184. public struct MultipleSized4096
  1185. {
  1186. public Sized4096 a;
  1187. public Sized4096 b;
  1188. public struct Provider : IArgumentProvider
  1189. {
  1190. public object Value => new MultipleSized4096 { a = new Sized4096(), b = new Sized4096() };
  1191. }
  1192. }
  1193. [TestCompiler(typeof(MultipleSized4096.Provider), typeof(Sized4096.Provider))]
  1194. public static void TestMultipleSized4096(ref MultipleSized4096 a, ref Sized4096 b)
  1195. {
  1196. a.a = b;
  1197. a.a.First = 42;
  1198. b = a.b;
  1199. }
  1200. [TestCompiler(typeof(MultipleSized4096.Provider), typeof(Sized4096.Provider), typeof(Sized4096.Provider))]
  1201. public static void TestMultipleSized4096CopyToAlloca(ref MultipleSized4096 a, ref Sized4096 b, ref Sized4096 c)
  1202. {
  1203. MultipleSized4096 d = default;
  1204. d.a = b;
  1205. b = d.b;
  1206. c = a.a;
  1207. a = d;
  1208. }
  1209. public unsafe struct Fixed4096
  1210. {
  1211. public fixed byte First[4096];
  1212. public struct Provider : IArgumentProvider
  1213. {
  1214. public object Value => new Fixed4096();
  1215. }
  1216. }
  1217. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1218. public static unsafe void TestFixed4096(ref Fixed4096 a, ref Fixed4096 b)
  1219. {
  1220. a = b;
  1221. }
  1222. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1223. public static unsafe void TestFixed4096ManualCopy(ref Fixed4096 a, ref Fixed4096 b)
  1224. {
  1225. for (int i = 0; i < UnsafeUtility.SizeOf<Fixed4096>(); i++)
  1226. {
  1227. a.First[i] = b.First[i];
  1228. }
  1229. }
  1230. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1231. public static unsafe void TestFixed4096CopyToAlloca(ref Fixed4096 a, ref Fixed4096 b)
  1232. {
  1233. Fixed4096 c = b;
  1234. c.First[4] = 42;
  1235. a = c;
  1236. }
  1237. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1238. public static unsafe void TestFixed4096CopyToStackAlloc0(ref Fixed4096 a, ref Fixed4096 b)
  1239. {
  1240. Fixed4096* c = stackalloc Fixed4096[1];
  1241. c->First[4] = 42;
  1242. a = *c;
  1243. }
  1244. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1245. public static unsafe void TestFixed4096CopyToStackAlloc1(ref Fixed4096 a, ref Fixed4096 b)
  1246. {
  1247. byte* bytes = stackalloc byte[4096];
  1248. Fixed4096* c = (Fixed4096*)bytes;
  1249. c->First[4] = 42;
  1250. a = *c;
  1251. }
  1252. public unsafe struct PointersInStruct
  1253. {
  1254. public byte* a;
  1255. public byte* b;
  1256. public struct Provider : IArgumentProvider
  1257. {
  1258. public object Value => new PointersInStruct { a = null, b = null };
  1259. }
  1260. }
  1261. [TestCompiler(typeof(PointersInStruct.Provider), typeof(Fixed4096.Provider))]
  1262. public static unsafe void TestPointersInStruct(ref PointersInStruct a, ref Fixed4096 b)
  1263. {
  1264. fixed (byte* ptr = b.First)
  1265. {
  1266. a.a = ptr;
  1267. }
  1268. a.b = a.a;
  1269. }
  1270. private static unsafe T GenericGetT<T>(T* t) where T : unmanaged
  1271. {
  1272. return *t;
  1273. }
  1274. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1275. public static unsafe void TestGetStructThroughGeneric(ref Fixed4096 a, ref Fixed4096 b)
  1276. {
  1277. fixed (void* ptr = &a)
  1278. {
  1279. var elem = GenericGetT<Fixed4096>((Fixed4096*) ptr);
  1280. b = elem;
  1281. }
  1282. }
  1283. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1284. public static unsafe void TestGetStructThroughReadArrayElement(ref Fixed4096 a, ref Fixed4096 b)
  1285. {
  1286. fixed (void* ptr = &a)
  1287. {
  1288. var elem = UnsafeUtility.ReadArrayElement<Fixed4096>(ptr, 0);
  1289. b = elem;
  1290. }
  1291. }
  1292. [TestCompiler(typeof(Fixed4096.Provider), typeof(Fixed4096.Provider))]
  1293. public static unsafe void TestSetStructThroughWriteArrayElement(ref Fixed4096 a, ref Fixed4096 b)
  1294. {
  1295. fixed (void* ptr = &a)
  1296. {
  1297. var elem = a;
  1298. UnsafeUtility.WriteArrayElement(ptr, 0, elem);
  1299. }
  1300. }
  1301. private struct Fixed1021
  1302. {
  1303. public unsafe fixed byte Data[1021];
  1304. }
  1305. [TestCompiler(typeof(Fixed4096.Provider))]
  1306. public static unsafe void TestGetSetStructThroughReadWriteArrayElement(ref Fixed4096 a)
  1307. {
  1308. fixed (void* ptr1 = &a)
  1309. {
  1310. var ptr2 = (byte*) ptr1 + 1;
  1311. UnsafeUtility.WriteArrayElement(ptr1, 0, UnsafeUtility.ReadArrayElement<Fixed1021>(ptr2, 0));
  1312. }
  1313. }
  1314. [TestCompiler(typeof(Fixed4096.Provider))]
  1315. public static unsafe void TestGetSetStructThroughReadWriteArrayElementNoAlias(ref Fixed4096 a)
  1316. {
  1317. fixed (void* ptr1 = &a)
  1318. {
  1319. var ptr2 = (byte*) ptr1 + UnsafeUtility.SizeOf<Fixed1021>();
  1320. UnsafeUtility.WriteArrayElement(ptr1, 0, UnsafeUtility.ReadArrayElement<Fixed1021>(ptr2, 0));
  1321. }
  1322. }
  1323. [StructLayout(LayoutKind.Sequential, Size = 2)]
  1324. public struct WithPadding
  1325. {
  1326. public byte A;
  1327. public struct Provider : IArgumentProvider
  1328. {
  1329. public object Value => new WithPadding { A = 42 };
  1330. }
  1331. }
  1332. private static readonly WithPadding withPadding = new WithPadding { A = 42 };
  1333. [TestCompiler(typeof(ReturnBox))]
  1334. public static unsafe byte TestWithPadding(WithPadding* o)
  1335. {
  1336. *o = withPadding;
  1337. return withPadding.A;
  1338. }
  1339. [CompilerGenerated]
  1340. [StructLayout(LayoutKind.Sequential)]
  1341. public unsafe struct MyCompilerGeneratedButNotReally
  1342. {
  1343. public fixed int A[1];
  1344. }
  1345. private static readonly MyCompilerGeneratedButNotReally myCompilerGeneratedButNotReally = new MyCompilerGeneratedButNotReally { };
  1346. [TestCompiler(typeof(ReturnBox))]
  1347. public static unsafe int TestMyCompilerGeneratedButNotReallyStruct(MyCompilerGeneratedButNotReally* o)
  1348. {
  1349. *o = myCompilerGeneratedButNotReally;
  1350. fixed (int* a = myCompilerGeneratedButNotReally.A)
  1351. {
  1352. return *a;
  1353. }
  1354. }
  1355. public unsafe struct UninitFieldsAreZero
  1356. {
  1357. public fixed ushort a[3];
  1358. public fixed byte b[3];
  1359. public UninitFieldsAreZero(ushort x, ushort y, ushort z)
  1360. {
  1361. a[0] = x;
  1362. a[1] = y;
  1363. a[2] = z;
  1364. }
  1365. }
  1366. [TestCompiler(typeof(ReturnBox))]
  1367. public static unsafe void TestUninitFieldsAreZero(UninitFieldsAreZero* o)
  1368. {
  1369. o->a[0] = 42;
  1370. o->a[1] = 42;
  1371. o->a[2] = 42;
  1372. o->b[0] = 42;
  1373. o->b[1] = 42;
  1374. o->b[2] = 42;
  1375. var n = new UninitFieldsAreZero(13, 53, 4);
  1376. *o = n;
  1377. }
  1378. #pragma warning disable 0649
  1379. private struct ExplicitSizesMatchB
  1380. {
  1381. public uint U;
  1382. }
  1383. private struct ExplicitSizesMatchC
  1384. {
  1385. public ulong L;
  1386. public uint U;
  1387. public ushort S;
  1388. public byte B;
  1389. }
  1390. [StructLayout(LayoutKind.Explicit)]
  1391. private struct ExplicitSizesMatch
  1392. {
  1393. [FieldOffset(0)] public int A;
  1394. [FieldOffset(4)] public ExplicitSizesMatchB B;
  1395. [FieldOffset(4)] public ExplicitSizesMatchC C;
  1396. }
  1397. #pragma warning restore 0649
  1398. [TestCompiler]
  1399. public static unsafe int TestExplicitSizesMatch()
  1400. {
  1401. return sizeof(ExplicitSizesMatch);
  1402. }
  1403. #if BURST_TESTS_ONLY
  1404. private struct ExplicitLayoutAndBoolStruct
  1405. {
  1406. [StructLayout(LayoutKind.Explicit)]
  1407. public struct ExplicitLayoutStruct
  1408. {
  1409. [FieldOffset(0)]
  1410. public byte Byte;
  1411. }
  1412. // Having `bool` AND a field whose type is an explicit-layout struct
  1413. // causes .NET to fallback to auto-layout for the containing struct.
  1414. public bool Bool;
  1415. public ExplicitLayoutStruct ExplicitLayout;
  1416. public long Int64;
  1417. }
  1418. #if NETFRAMEWORK
  1419. // Note on Net7 the issue this is testing for is fixed.
  1420. // This test just exists to verify that .NET does indeed do the fallback
  1421. // to auto-layout that we expect it does, since this is the underlying
  1422. // reason for us to prevent the combination of
  1423. // "bool + explicit-layout struct".
  1424. [Test]
  1425. [RestrictPlatform(".NET falls back to auto-layout for this struct, but Mono doesn't", Platform.Windows)]
  1426. public static unsafe void TestExplicitLayoutAndBoolCausesDotNetToFallbackToAutoLayout()
  1427. {
  1428. var s = new ExplicitLayoutAndBoolStruct();
  1429. var offsetStart = (IntPtr)(&s);
  1430. var offsetField = (IntPtr)(&s.Int64);
  1431. var offset = offsetField.ToInt64() - offsetStart.ToInt64();
  1432. // We would expect the offset to the `Int64` field to be 8.
  1433. // But because .NET falls back to auto-layout,
  1434. // and places the `Int64` field first,
  1435. // the offset is actually 0.
  1436. Assert.AreEqual((long)0, offset);
  1437. }
  1438. #endif
  1439. [TestCompiler(EnableAutoLayoutFallbackCheck = true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_NonBlittableAndNonManagedSequentialStructNotSupported)]
  1440. public static long TestExplicitLayoutAndBoolIsNotSupported()
  1441. {
  1442. return new ExplicitLayoutAndBoolStruct { Int64 = 8 }.Int64;
  1443. }
  1444. private struct ExplicitLayoutNestedAndBoolStruct
  1445. {
  1446. public struct SequentialLayoutStruct
  1447. {
  1448. #pragma warning disable 0649
  1449. public ExplicitLayoutStruct ExplicitLayout;
  1450. #pragma warning restore 0649
  1451. }
  1452. [StructLayout(LayoutKind.Explicit)]
  1453. public struct ExplicitLayoutStruct
  1454. {
  1455. [FieldOffset(0)]
  1456. public byte Byte;
  1457. }
  1458. #pragma warning disable 0649
  1459. public bool Bool;
  1460. public SequentialLayoutStruct SequentialLayout;
  1461. #pragma warning restore 0649
  1462. public long Int64;
  1463. }
  1464. [TestCompiler(EnableAutoLayoutFallbackCheck = true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_NonBlittableAndNonManagedSequentialStructNotSupported)]
  1465. public static long TestExplicitLayoutNestedAndBoolIsNotSupported()
  1466. {
  1467. return new ExplicitLayoutNestedAndBoolStruct { Int64 = 8 }.Int64;
  1468. }
  1469. private struct ExplicitLayoutStructAndBoolWithMarshalAs
  1470. {
  1471. [StructLayout(LayoutKind.Explicit)]
  1472. public struct ExplicitLayoutStruct
  1473. {
  1474. [FieldOffset(0)]
  1475. public byte Byte;
  1476. }
  1477. #pragma warning disable 0649
  1478. [MarshalAs(UnmanagedType.U1)]
  1479. public bool Bool;
  1480. public ExplicitLayoutStruct ExplicitLayout;
  1481. #pragma warning restore 0649
  1482. public long Int64;
  1483. }
  1484. [TestCompiler(EnableAutoLayoutFallbackCheck = true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_NonBlittableAndNonManagedSequentialStructNotSupported)]
  1485. public static unsafe long TestExplicitLayoutAndBoolWithMarshalAsIsNotSupported()
  1486. {
  1487. return new ExplicitLayoutStructAndBoolWithMarshalAs { Int64 = 8 }.Int64;
  1488. }
  1489. #endif
  1490. private struct SequentialLayoutAndBoolStruct
  1491. {
  1492. public struct SequentialLayoutStruct
  1493. {
  1494. #pragma warning disable 0649
  1495. public byte Byte;
  1496. #pragma warning restore 0649
  1497. }
  1498. #pragma warning disable 0649
  1499. public bool Bool;
  1500. public SequentialLayoutStruct SequentialLayout;
  1501. #pragma warning restore 0649
  1502. public long Int64;
  1503. }
  1504. [TestCompiler]
  1505. public static unsafe long TestSequentialLayoutAndBoolIsSupported()
  1506. {
  1507. return new SequentialLayoutAndBoolStruct { Int64 = 8 }.Int64;
  1508. }
  1509. }
  1510. }