CUDAx.Parser.pas 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //
  2. // The graphics platform GLXcene https://github.com/glscene
  3. //
  4. unit CUDAx.Parser;
  5. (*
  6. Helper unit for parsing CU modules and get information about.
  7. kernel's functions, textures, shared and constants memory.
  8. *)
  9. interface
  10. uses
  11. System.Classes,
  12. System.SysUtils,
  13. GLX.Strings,
  14. CUDAx.RunTime;
  15. type
  16. TCUDAType =
  17. (
  18. customType,
  19. char1,
  20. uchar1,
  21. char2,
  22. uchar2,
  23. char3,
  24. uchar3,
  25. char4,
  26. uchar4,
  27. short1,
  28. ushort1,
  29. short2,
  30. ushort2,
  31. short3,
  32. ushort3,
  33. short4,
  34. ushort4,
  35. int1,
  36. uint1,
  37. int2,
  38. uint2,
  39. int3,
  40. uint3,
  41. int4,
  42. uint4,
  43. long1,
  44. ulong1,
  45. long2,
  46. ulong2,
  47. long3,
  48. ulong3,
  49. long4,
  50. ulong4,
  51. float1,
  52. float2,
  53. float3,
  54. float4,
  55. longlong1,
  56. ulonglong1,
  57. longlong2,
  58. ulonglong2,
  59. longlong3,
  60. ulonglong3,
  61. longlong4,
  62. ulonglong4,
  63. double1,
  64. double2,
  65. double3,
  66. double4,
  67. int8,
  68. int16,
  69. int32,
  70. uint8,
  71. uint16,
  72. uint32
  73. );
  74. TCUDATexRefInfo = record
  75. Name: string;
  76. DataType: TCUDAType;
  77. Dim: Byte;
  78. ReadMode: TcudaTextureReadMode;
  79. end;
  80. TCUDAFuncArgInfo = record
  81. Name: string;
  82. DataType: TCUDAType;
  83. CustomType: string;
  84. Ref: Boolean;
  85. end;
  86. TCUDAFuncInfo = record
  87. Name: string;
  88. KernelName: string;
  89. Args: array of TCUDAFuncArgInfo;
  90. end;
  91. TCUDAConstantInfo = record
  92. Name: string;
  93. DataType: TCUDAType;
  94. CustomType: string;
  95. Ref: Boolean;
  96. DefValue: Boolean;
  97. end;
  98. TCUDAModuleInfo = class(TObject)
  99. private
  100. ping, pong: TStrings;
  101. procedure Reset;
  102. procedure BreakStrings(inlist, outlist: TStrings);
  103. procedure RemoveComents(inlist, outlist: TStrings);
  104. procedure RemoveSpaces(inlist, outlist: TStrings);
  105. procedure ReplaceUnsigned(inlist, outlist: TStrings);
  106. procedure FindTexRef(inlist: TStrings);
  107. procedure FindConst(inlist: TStrings);
  108. procedure FindFunc(inlist: TStrings);
  109. procedure FindFuncKernelName(inlist: TStrings);
  110. public
  111. Owner: TComponent;
  112. TexRef: array of TCUDATexRefInfo;
  113. Func: array of TCUDAFuncInfo;
  114. Constant: array of TCUDAConstantInfo;
  115. constructor Create;
  116. destructor Destroy; override;
  117. procedure ParseModule(ASource, AProduct: TStrings);
  118. end;
  119. //----------------------------------------------------------------
  120. implementation
  121. //----------------------------------------------------------------
  122. const
  123. WordDelimiters: set of AnsiChar = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0','_'];
  124. sCUDAType: array[TCUDAType] of string =
  125. (
  126. '',
  127. 'char',
  128. 'uchar',
  129. 'char2',
  130. 'uchar2',
  131. 'char3',
  132. 'uchar3',
  133. 'char4',
  134. 'uchar4',
  135. 'short',
  136. 'ushort',
  137. 'short2',
  138. 'ushort2',
  139. 'short3',
  140. 'ushort3',
  141. 'short4',
  142. 'ushort4',
  143. 'int',
  144. 'uint',
  145. 'int2',
  146. 'uint2',
  147. 'int3',
  148. 'uint3',
  149. 'int4',
  150. 'uint4',
  151. 'long',
  152. 'ulong',
  153. 'long2',
  154. 'ulong2',
  155. 'long3',
  156. 'ulong3',
  157. 'long4',
  158. 'ulong4',
  159. 'float',
  160. 'float2',
  161. 'float3',
  162. 'float4',
  163. 'longlong',
  164. 'ulonglong',
  165. 'longlong2',
  166. 'ulonglong2',
  167. 'longlong3',
  168. 'ulonglong3',
  169. 'longlong4',
  170. 'ulonglong4',
  171. 'double',
  172. 'double2',
  173. 'double3',
  174. 'double4',
  175. 'int8',
  176. 'int16',
  177. 'int32',
  178. 'uint8',
  179. 'uint16',
  180. 'uint32'
  181. );
  182. function StrToCUDAType(const AToken: string): TCUDAType;
  183. var
  184. T: TCUDAType;
  185. begin
  186. for T := char1 to uint32 do
  187. if AToken = sCUDAType[T] then
  188. begin
  189. exit(T);
  190. end;
  191. Result := customType;
  192. end;
  193. procedure TCUDAModuleInfo.BreakStrings(inlist, outlist: TStrings);
  194. var
  195. i: Integer;
  196. str, accum: string;
  197. c: Char;
  198. begin
  199. str := inlist.Text;
  200. outlist.Clear;
  201. accum := '';
  202. for I := 1 to Length(str) do
  203. begin
  204. c := str[I];
  205. if CharInSet(c, WordDelimiters) then
  206. begin
  207. if Length(accum) > 0 then
  208. begin
  209. outlist.Add(accum);
  210. accum := '';
  211. end;
  212. outlist.Add(c);
  213. end
  214. else
  215. accum := accum + str[I];
  216. end;
  217. end;
  218. procedure TCUDAModuleInfo.RemoveComents(inlist, outlist: TStrings);
  219. var
  220. bSkipToLineBreak: Boolean;
  221. bSkipToRemarkEnd: Boolean;
  222. i: Integer;
  223. str1, str2: string;
  224. begin
  225. outlist.Clear;
  226. bSkipToLineBreak := False;
  227. bSkipToRemarkEnd := False;
  228. for I := 0 to inlist.Count - 2 do
  229. begin
  230. str1 := inlist[I];
  231. str2 := inlist[I+1];
  232. if bSkipToLineBreak then
  233. begin
  234. if (str1 = #13) then
  235. bSkipToLineBreak := False;
  236. continue;
  237. end;
  238. if bSkipToRemarkEnd then
  239. begin
  240. if (str1 = '*') and (str2 = '/') then
  241. bSkipToRemarkEnd := False;
  242. continue;
  243. end;
  244. if (str1 = '/') and (str2 = '/') then
  245. begin
  246. bSkipToLineBreak := True;
  247. continue;
  248. end
  249. else if (str1 = '/') and (str2 = '*') then
  250. begin
  251. bSkipToRemarkEnd := True;
  252. continue;
  253. end;
  254. outlist.Add(str1);
  255. end;
  256. end;
  257. procedure TCUDAModuleInfo.RemoveSpaces(inlist, outlist: TStrings);
  258. var
  259. i: Integer;
  260. begin
  261. outlist.Clear;
  262. for I := 0 to inlist.Count - 2 do
  263. if inlist[i] > #32 then
  264. outlist.Add(inlist[i]);
  265. end;
  266. procedure TCUDAModuleInfo.ReplaceUnsigned(inlist, outlist: TStrings);
  267. var
  268. I: Integer;
  269. begin
  270. outlist.Clear;
  271. I := 0;
  272. repeat
  273. if (inlist[I] = 'unsigned') and (inlist[I+1] = 'int') then
  274. begin
  275. outlist.Add('uint32');
  276. Inc(I);
  277. end
  278. else
  279. outlist.Add(inlist[I]);
  280. Inc(I);
  281. until I >= inlist.Count;
  282. end;
  283. procedure TCUDAModuleInfo.FindTexRef(inlist: TStrings);
  284. var
  285. i, p, e: Integer;
  286. texInfo: TCUDATexRefInfo;
  287. begin
  288. for I := 0 to inlist.Count - 1 do
  289. begin
  290. if UpperCase(inlist[i]) = 'TEXTURE' then
  291. begin
  292. if inlist[i+1] <> '<' then
  293. continue;
  294. texInfo.DataType := StrToCUDAType(inlist[i+2]);
  295. if inlist[i+3] <> ',' then
  296. continue;
  297. Val(inlist[i+4], texInfo.Dim, e);
  298. if e <> 0 then
  299. Continue;
  300. p := 5;
  301. if inlist[i+5] = ',' then
  302. begin
  303. if inlist[i+6] = 'cudaReadModeElementType' then
  304. texInfo.ReadMode := cudaReadModeElementType
  305. else if inlist[i+6] = 'cudaReadModeNormalizedFloat' then
  306. texInfo.ReadMode := cudaReadModeNormalizedFloat
  307. else
  308. Continue;
  309. p := 7;
  310. end;
  311. if inlist[i+p] <> '>' then
  312. continue;
  313. texInfo.Name := inlist[i+p+1];
  314. SetLength(TexRef, Length(TexRef)+1);
  315. TexRef[High(TexRef)] := texInfo;
  316. end;
  317. end;
  318. end;
  319. constructor TCUDAModuleInfo.Create;
  320. begin
  321. ping := TStringList.Create;
  322. pong := TStringList.Create;
  323. end;
  324. destructor TCUDAModuleInfo.Destroy;
  325. begin
  326. ping.Destroy;
  327. pong.Destroy;
  328. end;
  329. procedure TCUDAModuleInfo.FindConst(inlist: TStrings);
  330. var
  331. i, p: Integer;
  332. constInfo: TCUDAConstantInfo;
  333. begin
  334. for I := 0 to inlist.Count - 1 do
  335. begin
  336. if UpperCase(inlist[i]) = '__CONSTANT__' then
  337. begin
  338. p := i+1;
  339. if inlist[p] = 'static' then
  340. Inc(p);
  341. constInfo.DataType := StrToCUDAType(inlist[p]);
  342. if constInfo.DataType = customType then
  343. constInfo.CustomType := inlist[p]
  344. else
  345. constInfo.CustomType := '';
  346. Inc(p);
  347. if inlist[p] = '*' then
  348. begin
  349. constInfo.Ref := True;
  350. Inc(p);
  351. end
  352. else
  353. constInfo.Ref := False;
  354. constInfo.Name := inlist[p];
  355. Inc(p);
  356. constInfo.DefValue := False;
  357. while p < inlist.Count do
  358. begin
  359. if inlist[p] = '=' then
  360. begin
  361. constInfo.DefValue := True;
  362. break;
  363. end
  364. else if inlist[p] = ';' then
  365. break;
  366. Inc(p);
  367. end;
  368. SetLength(Constant, Length(Constant)+1);
  369. Constant[High(Constant)] := constInfo;
  370. end;
  371. end;
  372. end;
  373. procedure TCUDAModuleInfo.FindFunc(inlist: TStrings);
  374. var
  375. i, p: Integer;
  376. funcInfo: TCUDAFuncInfo;
  377. argInfo: TCUDAFuncArgInfo;
  378. begin
  379. for I := 0 to inlist.Count - 1 do
  380. begin
  381. if UpperCase(inlist[i]) = '__GLOBAL__' then
  382. begin
  383. if inlist[i+1] <> 'void' then
  384. Continue;
  385. funcInfo.Name := inlist[i+2];
  386. funcInfo.KernelName := '';
  387. if inlist[i+3] <> '(' then
  388. Continue;
  389. p := 4;
  390. funcInfo.Args := nil;
  391. while inlist[i+p] <> ')' do
  392. begin
  393. if inlist[i+p] = ',' then
  394. begin
  395. inc(p);
  396. Continue;
  397. end;
  398. argInfo.DataType := StrToCUDAType(inlist[i+p]);
  399. if argInfo.DataType = customType then
  400. argInfo.CustomType := inlist[i+p]
  401. else
  402. argInfo.CustomType := '';
  403. Inc(p);
  404. if inlist[i+p] = '*' then
  405. begin
  406. argInfo.Ref := True;
  407. Inc(p);
  408. end
  409. else
  410. argInfo.Ref := False;
  411. argInfo.Name := inlist[i+p];
  412. SetLength(funcInfo.Args, Length(funcInfo.Args)+1);
  413. funcInfo.Args[High(funcInfo.Args)] := argInfo;
  414. inc(p);
  415. end;
  416. SetLength(Func, Length(Func)+1);
  417. Func[High(Func)] := funcInfo;
  418. end;
  419. end;
  420. end;
  421. procedure TCUDAModuleInfo.FindFuncKernelName(inlist: TStrings);
  422. var
  423. I, J, P: Integer;
  424. LStr: string;
  425. begin
  426. for J := 0 to inlist.Count - 1 do
  427. begin
  428. LStr := inlist[J];
  429. P := Pos('.entry', LStr);
  430. if P > 0 then
  431. begin
  432. Delete(LStr, 1, P+6);
  433. P := Pos(' ', LStr);
  434. if P < 1 then
  435. continue;
  436. LStr := Copy(LStr, 1, P-1);
  437. for I := 0 to High(Func) do
  438. begin
  439. if Pos(Func[I].Name, LStr) > 0 then
  440. begin
  441. if Length(Func[I].KernelName) > Length(LStr) then
  442. continue;
  443. Func[I].KernelName := LStr;
  444. break;
  445. end;
  446. end;
  447. end;
  448. end;
  449. end;
  450. procedure TCUDAModuleInfo.Reset;
  451. var
  452. i: Integer;
  453. begin
  454. TexRef := nil;
  455. Constant:= nil;
  456. for I := 0 to High(Func) do
  457. Func[I].Args := nil;
  458. Func := nil;
  459. end;
  460. procedure TCUDAModuleInfo.ParseModule(ASource, AProduct: TStrings);
  461. begin
  462. Reset;
  463. BreakStrings(ASource, ping);
  464. RemoveComents(ping, pong);
  465. RemoveSpaces(pong, ping);
  466. ReplaceUnsigned(ping, pong);
  467. FindTexRef(pong);
  468. FindConst(pong);
  469. FindFunc(pong);
  470. // Double call to confidence
  471. FindFuncKernelName(AProduct);
  472. FindFuncKernelName(AProduct);
  473. end;
  474. end.