CUDA.Parser.pas 9.8 KB

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