CUDA.Parser.pas 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //
  2. // The graphics engine 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. implementation //--------------------------------------------------------------
  119. const
  120. WordDelimiters: set of AnsiChar = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0','_'];
  121. sCUDAType: array[TCUDAType] of string =
  122. (
  123. '',
  124. 'char',
  125. 'uchar',
  126. 'char2',
  127. 'uchar2',
  128. 'char3',
  129. 'uchar3',
  130. 'char4',
  131. 'uchar4',
  132. 'short',
  133. 'ushort',
  134. 'short2',
  135. 'ushort2',
  136. 'short3',
  137. 'ushort3',
  138. 'short4',
  139. 'ushort4',
  140. 'int',
  141. 'uint',
  142. 'int2',
  143. 'uint2',
  144. 'int3',
  145. 'uint3',
  146. 'int4',
  147. 'uint4',
  148. 'long',
  149. 'ulong',
  150. 'long2',
  151. 'ulong2',
  152. 'long3',
  153. 'ulong3',
  154. 'long4',
  155. 'ulong4',
  156. 'float',
  157. 'float2',
  158. 'float3',
  159. 'float4',
  160. 'longlong',
  161. 'ulonglong',
  162. 'longlong2',
  163. 'ulonglong2',
  164. 'longlong3',
  165. 'ulonglong3',
  166. 'longlong4',
  167. 'ulonglong4',
  168. 'double',
  169. 'double2',
  170. 'double3',
  171. 'double4',
  172. 'int8',
  173. 'int16',
  174. 'int32',
  175. 'uint8',
  176. 'uint16',
  177. 'uint32'
  178. );
  179. function StrToCUDAType(const AToken: string): TCUDAType;
  180. var
  181. T: TCUDAType;
  182. begin
  183. for T := char1 to uint32 do
  184. if AToken = sCUDAType[T] then
  185. begin
  186. exit(T);
  187. end;
  188. Result := customType;
  189. end;
  190. procedure TCUDAModuleInfo.BreakStrings(inlist, outlist: TStrings);
  191. var
  192. i: Integer;
  193. str, accum: string;
  194. c: Char;
  195. begin
  196. str := inlist.Text;
  197. outlist.Clear;
  198. accum := '';
  199. for I := 1 to Length(str) do
  200. begin
  201. c := str[I];
  202. if CharInSet(c, WordDelimiters) then
  203. begin
  204. if Length(accum) > 0 then
  205. begin
  206. outlist.Add(accum);
  207. accum := '';
  208. end;
  209. outlist.Add(c);
  210. end
  211. else
  212. accum := accum + str[I];
  213. end;
  214. end;
  215. procedure TCUDAModuleInfo.RemoveComents(inlist, outlist: TStrings);
  216. var
  217. bSkipToLineBreak: Boolean;
  218. bSkipToRemarkEnd: Boolean;
  219. i: Integer;
  220. str1, str2: string;
  221. begin
  222. outlist.Clear;
  223. bSkipToLineBreak := False;
  224. bSkipToRemarkEnd := False;
  225. for I := 0 to inlist.Count - 2 do
  226. begin
  227. str1 := inlist[I];
  228. str2 := inlist[I+1];
  229. if bSkipToLineBreak then
  230. begin
  231. if (str1 = #13) then
  232. bSkipToLineBreak := False;
  233. continue;
  234. end;
  235. if bSkipToRemarkEnd then
  236. begin
  237. if (str1 = '*') and (str2 = '/') then
  238. bSkipToRemarkEnd := False;
  239. continue;
  240. end;
  241. if (str1 = '/') and (str2 = '/') then
  242. begin
  243. bSkipToLineBreak := True;
  244. continue;
  245. end
  246. else if (str1 = '/') and (str2 = '*') then
  247. begin
  248. bSkipToRemarkEnd := True;
  249. continue;
  250. end;
  251. outlist.Add(str1);
  252. end;
  253. end;
  254. procedure TCUDAModuleInfo.RemoveSpaces(inlist, outlist: TStrings);
  255. var
  256. i: Integer;
  257. begin
  258. outlist.Clear;
  259. for I := 0 to inlist.Count - 2 do
  260. if inlist[i] > #32 then
  261. outlist.Add(inlist[i]);
  262. end;
  263. procedure TCUDAModuleInfo.ReplaceUnsigned(inlist, outlist: TStrings);
  264. var
  265. I: Integer;
  266. begin
  267. outlist.Clear;
  268. I := 0;
  269. repeat
  270. if (inlist[I] = 'unsigned') and (inlist[I+1] = 'int') then
  271. begin
  272. outlist.Add('uint32');
  273. Inc(I);
  274. end
  275. else
  276. outlist.Add(inlist[I]);
  277. Inc(I);
  278. until I >= inlist.Count;
  279. end;
  280. procedure TCUDAModuleInfo.FindTexRef(inlist: TStrings);
  281. var
  282. i, p, e: Integer;
  283. texInfo: TCUDATexRefInfo;
  284. begin
  285. for I := 0 to inlist.Count - 1 do
  286. begin
  287. if UpperCase(inlist[i]) = 'TEXTURE' then
  288. begin
  289. if inlist[i+1] <> '<' then
  290. continue;
  291. texInfo.DataType := StrToCUDAType(inlist[i+2]);
  292. if inlist[i+3] <> ',' then
  293. continue;
  294. Val(inlist[i+4], texInfo.Dim, e);
  295. if e <> 0 then
  296. Continue;
  297. p := 5;
  298. if inlist[i+5] = ',' then
  299. begin
  300. if inlist[i+6] = 'cudaReadModeElementType' then
  301. texInfo.ReadMode := cudaReadModeElementType
  302. else if inlist[i+6] = 'cudaReadModeNormalizedFloat' then
  303. texInfo.ReadMode := cudaReadModeNormalizedFloat
  304. else
  305. Continue;
  306. p := 7;
  307. end;
  308. if inlist[i+p] <> '>' then
  309. continue;
  310. texInfo.Name := inlist[i+p+1];
  311. SetLength(TexRef, Length(TexRef)+1);
  312. TexRef[High(TexRef)] := texInfo;
  313. end;
  314. end;
  315. end;
  316. constructor TCUDAModuleInfo.Create;
  317. begin
  318. ping := TStringList.Create;
  319. pong := TStringList.Create;
  320. end;
  321. destructor TCUDAModuleInfo.Destroy;
  322. begin
  323. ping.Destroy;
  324. pong.Destroy;
  325. end;
  326. procedure TCUDAModuleInfo.FindConst(inlist: TStrings);
  327. var
  328. i, p: Integer;
  329. constInfo: TCUDAConstantInfo;
  330. begin
  331. for I := 0 to inlist.Count - 1 do
  332. begin
  333. if UpperCase(inlist[i]) = '__CONSTANT__' then
  334. begin
  335. p := i+1;
  336. if inlist[p] = 'static' then
  337. Inc(p);
  338. constInfo.DataType := StrToCUDAType(inlist[p]);
  339. if constInfo.DataType = customType then
  340. constInfo.CustomType := inlist[p]
  341. else
  342. constInfo.CustomType := '';
  343. Inc(p);
  344. if inlist[p] = '*' then
  345. begin
  346. constInfo.Ref := True;
  347. Inc(p);
  348. end
  349. else
  350. constInfo.Ref := False;
  351. constInfo.Name := inlist[p];
  352. Inc(p);
  353. constInfo.DefValue := False;
  354. while p < inlist.Count do
  355. begin
  356. if inlist[p] = '=' then
  357. begin
  358. constInfo.DefValue := True;
  359. break;
  360. end
  361. else if inlist[p] = ';' then
  362. break;
  363. Inc(p);
  364. end;
  365. SetLength(Constant, Length(Constant)+1);
  366. Constant[High(Constant)] := constInfo;
  367. end;
  368. end;
  369. end;
  370. procedure TCUDAModuleInfo.FindFunc(inlist: TStrings);
  371. var
  372. i, p: Integer;
  373. funcInfo: TCUDAFuncInfo;
  374. argInfo: TCUDAFuncArgInfo;
  375. begin
  376. for I := 0 to inlist.Count - 1 do
  377. begin
  378. if UpperCase(inlist[i]) = '__GLOBAL__' then
  379. begin
  380. if inlist[i+1] <> 'void' then
  381. Continue;
  382. funcInfo.Name := inlist[i+2];
  383. funcInfo.KernelName := '';
  384. if inlist[i+3] <> '(' then
  385. Continue;
  386. p := 4;
  387. funcInfo.Args := nil;
  388. while inlist[i+p] <> ')' do
  389. begin
  390. if inlist[i+p] = ',' then
  391. begin
  392. inc(p);
  393. Continue;
  394. end;
  395. argInfo.DataType := StrToCUDAType(inlist[i+p]);
  396. if argInfo.DataType = customType then
  397. argInfo.CustomType := inlist[i+p]
  398. else
  399. argInfo.CustomType := '';
  400. Inc(p);
  401. if inlist[i+p] = '*' then
  402. begin
  403. argInfo.Ref := True;
  404. Inc(p);
  405. end
  406. else
  407. argInfo.Ref := False;
  408. argInfo.Name := inlist[i+p];
  409. SetLength(funcInfo.Args, Length(funcInfo.Args)+1);
  410. funcInfo.Args[High(funcInfo.Args)] := argInfo;
  411. inc(p);
  412. end;
  413. SetLength(Func, Length(Func)+1);
  414. Func[High(Func)] := funcInfo;
  415. end;
  416. end;
  417. end;
  418. procedure TCUDAModuleInfo.FindFuncKernelName(inlist: TStrings);
  419. var
  420. I, J, P: Integer;
  421. LStr: string;
  422. begin
  423. for J := 0 to inlist.Count - 1 do
  424. begin
  425. LStr := inlist[J];
  426. P := Pos('.entry', LStr);
  427. if P > 0 then
  428. begin
  429. Delete(LStr, 1, P+6);
  430. P := Pos(' ', LStr);
  431. if P < 1 then
  432. continue;
  433. LStr := Copy(LStr, 1, P-1);
  434. for I := 0 to High(Func) do
  435. begin
  436. if Pos(Func[I].Name, LStr) > 0 then
  437. begin
  438. if Length(Func[I].KernelName) > Length(LStr) then
  439. continue;
  440. Func[I].KernelName := LStr;
  441. break;
  442. end;
  443. end;
  444. end;
  445. end;
  446. end;
  447. procedure TCUDAModuleInfo.Reset;
  448. var
  449. i: Integer;
  450. begin
  451. TexRef := nil;
  452. Constant:= nil;
  453. for I := 0 to High(Func) do
  454. Func[I].Args := nil;
  455. Func := nil;
  456. end;
  457. procedure TCUDAModuleInfo.ParseModule(ASource, AProduct: TStrings);
  458. begin
  459. Reset;
  460. BreakStrings(ASource, ping);
  461. RemoveComents(ping, pong);
  462. RemoveSpaces(pong, ping);
  463. ReplaceUnsigned(ping, pong);
  464. FindTexRef(pong);
  465. FindConst(pong);
  466. FindFunc(pong);
  467. // Double call to confidence
  468. FindFuncKernelName(AProduct);
  469. FindFuncKernelName(AProduct);
  470. end;
  471. end.