1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "CISALinker.h"
10 #include <stdio.h>
11
12 // *** Macros ***
13
14 #define ASSERT(assertion, ...) \
15 if (!(assertion)) { \
16 fprintf(stderr, "Error: " __VA_ARGS__); \
17 fprintf(stderr, "!\n"); \
18 return 1; \
19 }
20
21 #define ALLOC_ASSERT(allocation) \
22 ASSERT( \
23 allocation, "Memory allocation failure at %s:%u", \
24 __FILE__, __LINE__);
25
26 #define INTERNAL_ASSERT(assertion) \
27 ASSERT( \
28 assertion, "Internal error at %s:%u", \
29 __FILE__, __LINE__)
30
31
32 #define TRY(x) \
33 if ((x)) { \
34 return 1; \
35 }
36
37 #define BUF_APPEND_SCALAR(X) \
38 memcpy( \
39 (char *)_cisaObjInfos[_numCisaObjInfos].buf + _cisaEmitBufOffset, \
40 &X, sizeof(X)); \
41 _cisaEmitBufOffset += sizeof(X);
42
43 #define BUF_APPEND_VECTOR(X, Y) \
44 memcpy( \
45 (char *)_cisaObjInfos[_numCisaObjInfos].buf + _cisaEmitBufOffset, \
46 (X), Y); \
47 _cisaEmitBufOffset += Y;
48
49 #define CLOSURE(x) ((x).scratch)
50 #define UNITCLOSURE(x) (((CompiledUnitClosure *) CLOSURE(x)))
51 #define VARCLOSURE(x) (((CompiledVarClosure *) CLOSURE(x)))
52
53 #define cisaBytePos byte_pos
54
55 // *** Public functions ***
56
CISALinker(int numOptions,const char * options[],vISA::Mem_Manager & mem,ExternalHeapAllocator * externalAllocator)57 CISALinker::CISALinker(
58 int numOptions, const char *options[],
59 vISA::Mem_Manager& mem, ExternalHeapAllocator *externalAllocator)
60 : _numOptions(numOptions), _options(options), _mem(mem),
61 _countLinkedUnits(0), _countLinkedVars(0), _cisaEmitBufOffset(0),
62 _numCisaObjInfos(0), _cisaObjInfos(NULL)
63 {
64 _linkedUnitIndexToClosureMap.reserve(64);
65 if (externalAllocator) {
66 _allocator = externalAllocator;
67 }
68 else {
69 _allocator = (ExternalHeapAllocator*) malloc;
70 }
71 }
72
~CISALinker()73 CISALinker::~CISALinker()
74 {
75 }
76
77 int
LinkCisaMemObjs(const char * knlName,int numCisaObjs,const CisaObj cisaObjs[],CisaObj & cisaLinkedObj)78 CISALinker::LinkCisaMemObjs(
79 const char* knlName, int numCisaObjs, const CisaObj cisaObjs[],
80 CisaObj& cisaLinkedObj)
81 {
82 TRY(AllocateCisaObjInfos(numCisaObjs));
83
84 for (int i = 0; i < numCisaObjs; i++) {
85 TRY(ReadCisaMemObj(cisaObjs[i], _cisaObjInfos[i]));
86 }
87
88 std::string knlNameStr(knlName);
89 TRY(LinkCisaObjInfos(knlNameStr));
90 TRY(WriteCisaMemObj(cisaLinkedObj));
91
92 return 0;
93 }
94
95 int
LinkCisaFileObjs(const char * knlName,int numCisaObjs,const char * cisaObjs[],const char * cisaLinkedObj)96 CISALinker::LinkCisaFileObjs(
97 const char* knlName, int numCisaObjs, const char *cisaObjs[],
98 const char *cisaLinkedObj)
99 {
100 TRY(AllocateCisaObjInfos(numCisaObjs));
101
102 for (int i = 0; i < numCisaObjs; i++) {
103 const char *cisaExt = ".isa";
104 const char *cisaObjFile = cisaObjs[i];
105 const char *argExt = strstr(cisaObjFile, cisaExt);
106 ASSERT(
107 argExt != NULL && argExt[4] =='\0',
108 "CISA object file %s must have .isa extension", cisaObjFile);
109 TRY(ReadCisaFileObj(cisaObjFile, _cisaObjInfos[i]));
110 }
111
112 std::string knlNameStr(knlName);
113 TRY(LinkCisaObjInfos(knlNameStr));
114 TRY(WriteCisaFileObj(cisaLinkedObj));
115
116 return 0;
117 }
118
119 // *** Private functions ***
120
121 int
LinkCisaObjInfos(const std::string & knlName)122 CISALinker::LinkCisaObjInfos(const std::string& knlName)
123 {
124 CisaObjInfo& cisaLinkedObjInfo = _cisaObjInfos[_numCisaObjInfos];
125 TRY(InitGlobalInfoTables());
126 CompiledUnitClosureList cisaKnlClosureList;
127 TRY(CreateKernelClosures(knlName, cisaKnlClosureList));
128 CompiledUnitClosureList::iterator iter = cisaKnlClosureList.begin();
129
130 for (; iter != cisaKnlClosureList.end(); ++iter) {
131 CompiledUnitClosure& knlClosure = **iter;
132 CisaObjInfo& knlObjInfo = *knlClosure.unitObjInfo;
133 CompiledUnitClosureList localUnitClosureList;
134 localUnitClosureList.push_back(&knlClosure);
135 TRY(LinkLocalCisaObjInfos(knlObjInfo, localUnitClosureList));
136 TRY(LinkExternCisaObjInfos());
137 }
138
139 TRY(BuildLinkedCisaObj(cisaKnlClosureList));
140 TRY(UpdateLinkedCisaImageOffsetsAndSize());
141 ClearGlobalInfoTables();
142
143 return 0;
144 }
145
146 int
InitGlobalInfoTables()147 CISALinker::InitGlobalInfoTables()
148 {
149 for (int i = 0; i < _numCisaObjInfos; i++) {
150 CisaObjInfo& cisaObjInfo = _cisaObjInfos[i];
151
152 for (int j = 0; j < cisaObjInfo.hdr.num_global_functions; j++) {
153 int k = j + cisaObjInfo.hdr.num_extern_functions;
154 CompiledUnitInfo& unit = cisaObjInfo.hdr.functions[k];
155 CompiledUnitClosure *unitClosure =
156 (CompiledUnitClosure *)
157 _mem.alloc(sizeof(CompiledUnitClosure));
158 unitClosure->unit = &unit;
159 unitClosure->unitObjInfo = &cisaObjInfo;
160 unitClosure->linkedUnitIndex = -1;
161 CLOSURE(unit) = unitClosure;
162 std::string key(unit.name, unit.name_len);
163 std::pair<GlobalUnitNameToInfoMap::iterator, bool> loc =
164 _globalUnitNameToInfoMap.insert(
165 GlobalUnitNameToInfoMap::value_type(key, &unit));
166 ASSERT(
167 loc.second, "Found duplicate global functions for %s",
168 key.c_str());
169 }
170 }
171
172 for (int i = 0; i < _numCisaObjInfos; i++) {
173 CisaObjInfo& cisaObjInfo = _cisaObjInfos[i];
174
175 for (int j = 0; j < cisaObjInfo.hdr.num_global_variables; j++) {
176 int k = j + cisaObjInfo.hdr.num_extern_variables;
177 CompiledVarInfo& var = cisaObjInfo.hdr.filescope_variables[k];
178 CompiledVarClosure * varClosure =
179 (CompiledVarClosure *) _mem.alloc(sizeof(CompiledVarClosure));
180 varClosure->var = &var;
181 varClosure->varObjInfo = &cisaObjInfo;
182 varClosure->linkedVarIndex = -1;
183 CLOSURE(var) = varClosure;
184 std::string key((char *)var.name, var.name_len);
185 std::pair<GlobalVarNameToInfoMap::iterator, bool> loc =
186 _globalVarNameToInfoMap.insert(
187 GlobalVarNameToInfoMap::value_type(key, &var));
188 ASSERT(
189 loc.second, "Found duplicate global variables for %s",
190 key.c_str());
191 }
192 }
193
194 return 0;
195 }
196
197 inline void
ClearGlobalInfoTables()198 CISALinker::ClearGlobalInfoTables()
199 {
200 _globalUnitNameToInfoMap.clear();
201 _globalVarNameToInfoMap.clear();
202 }
203
204 inline int
GetGlobalUnitInfo(const std::string & unitName,CompiledUnitInfo * & globalUnitInfo)205 CISALinker::GetGlobalUnitInfo(
206 const std::string& unitName, CompiledUnitInfo *& globalUnitInfo)
207 {
208 GlobalUnitNameToInfoMap::iterator loc =
209 _globalUnitNameToInfoMap.find(unitName);
210 ASSERT(
211 loc != _globalUnitNameToInfoMap.end(),
212 "Cannot find global function %s", unitName.c_str());
213 globalUnitInfo = (*loc).second;
214
215 return 0;
216 }
217
218 inline int
GetGlobalUnitClosure(const std::string & unitName,CompiledUnitClosure * & globalUnitClosure)219 CISALinker::GetGlobalUnitClosure(
220 const std::string& unitName, CompiledUnitClosure *& globalUnitClosure)
221 {
222 CompiledUnitInfo *globalUnitInfo = NULL;
223 TRY(GetGlobalUnitInfo(unitName, globalUnitInfo));
224 globalUnitClosure = UNITCLOSURE(*globalUnitInfo);
225 INTERNAL_ASSERT(globalUnitClosure);
226
227 return 0;
228 }
229
230 inline int
GetGlobalVarInfo(const std::string & unitName,CompiledVarInfo * & globalVarInfo)231 CISALinker::GetGlobalVarInfo(
232 const std::string& unitName, CompiledVarInfo *& globalVarInfo)
233 {
234 GlobalVarNameToInfoMap::iterator loc =
235 _globalVarNameToInfoMap.find(unitName);
236 ASSERT(
237 loc != _globalVarNameToInfoMap.end(),
238 "Cannot find global variable %s", unitName.c_str());
239 globalVarInfo = (*loc).second;
240
241 return 0;
242 }
243
244 inline int
GetGlobalVarClosure(const std::string & unitName,CompiledVarClosure * & globalVarClosure)245 CISALinker::GetGlobalVarClosure(
246 const std::string& unitName, CompiledVarClosure *& globalVarClosure)
247 {
248 CompiledVarInfo *globalVarInfo = NULL;
249 TRY(GetGlobalVarInfo(unitName, globalVarInfo));
250 globalVarClosure = VARCLOSURE(*globalVarInfo);
251 INTERNAL_ASSERT(globalVarClosure);
252
253 return 0;
254 }
255
256 int
CreateKernelClosures(const std::string & knlName,CompiledUnitClosureList & knlClosureList)257 CISALinker::CreateKernelClosures(
258 const std::string& knlName, CompiledUnitClosureList& knlClosureList)
259 {
260 for (int i = 0; i < _numCisaObjInfos; i++) {
261 CisaObjInfo& cisaObjInfo = _cisaObjInfos[i];
262
263 for (int j = 0; j < cisaObjInfo.hdr.num_kernels; j++) {
264 CompiledUnitInfo& kernel = cisaObjInfo.hdr.kernels[j];
265
266 if ((knlName.size() == 0) ||
267 (knlName.size() == kernel.name_len &&
268 strncmp(kernel.name, knlName.c_str(), knlName.size()) == 0)) {
269 CompiledUnitClosure *knlClosure =
270 (CompiledUnitClosure *)
271 _mem.alloc(sizeof(CompiledUnitClosure));
272 ALLOC_ASSERT(knlClosure);
273 knlClosure->unit = &kernel;
274 knlClosure->unitObjInfo = &cisaObjInfo;
275 knlClosure->linkedUnitIndex = 0;
276 CLOSURE(kernel) = knlClosure;
277 knlClosureList.push_back(knlClosure);
278
279 if (knlName.size() && knlClosureList.size()) {
280 break;
281 }
282 }
283
284 if (knlName.size() && knlClosureList.size()) {
285 break;
286 }
287 }
288 }
289
290 if (knlName.size()) {
291 ASSERT(
292 knlClosureList.size() > 0,
293 "Cannot find kernel %s", knlName.c_str());
294 }
295 else {
296 ASSERT(
297 knlClosureList.size() > 0,
298 "Cannot find any kernel in input CISA objects");
299 }
300
301 return 0;
302 }
303
304 int
LinkLocalCisaObjInfos(CisaObjInfo & cisaObjInfo,CompiledUnitClosureList & localUnitClosureList)305 CISALinker::LinkLocalCisaObjInfos(
306 CisaObjInfo& cisaObjInfo, CompiledUnitClosureList& localUnitClosureList)
307 {
308 _localUnitMap = cisaObjInfo.hdr.functions;
309 _localVarMap = cisaObjInfo.hdr.filescope_variables;
310 CompiledUnitClosureList::iterator iter = localUnitClosureList.begin();
311
312 for ( ; iter != localUnitClosureList.end(); ++iter) {
313 TRY(LinkInDepUnits(**iter));
314 TRY(LinkInDepVars(**iter));
315 }
316
317 for (iter = _pendingLocalClosures.begin();
318 iter != _pendingLocalClosures.end(); ++iter) {
319 TRY(LinkInDepUnits(**iter));
320 TRY(LinkInDepVars(**iter));
321 }
322
323 for (iter = _pendingLocalClosures.begin();
324 iter != _pendingLocalClosures.end(); ++iter) {
325 TRY(RelocFunctionSyms(**iter));
326 TRY(RelocVariableSyms(**iter));
327 }
328
329 for (iter = localUnitClosureList.begin();
330 iter != localUnitClosureList.end(); ++iter) {
331 TRY(RelocFunctionSyms(**iter));
332 TRY(RelocVariableSyms(**iter));
333 }
334
335 _pendingLocalClosures.clear();
336 _localUnitMap = NULL;
337 _localVarMap = NULL;
338
339 return 0;
340 }
341
342 int
LinkExternCisaObjInfos()343 CISALinker::LinkExternCisaObjInfos()
344 {
345 CompiledUnitClosureList::iterator iter = _pendingExternClosures.begin();
346
347 for ( ; iter != _pendingExternClosures.end(); ++iter) {
348 CompiledUnitClosureList localUnitClosuresList;
349 localUnitClosuresList.push_back(*iter);
350
351 CompiledUnitClosureList::iterator jter = iter;
352
353 for ( ++jter; jter != _pendingExternClosures.end(); ) {
354
355 if ((*jter)->unitObjInfo == (*iter)->unitObjInfo) {
356 localUnitClosuresList.push_back(*jter);
357 CompiledUnitClosureList::iterator kter = jter++;
358 _pendingExternClosures.erase(kter);
359 }
360 else {
361 ++jter;
362 }
363 }
364
365 CisaObjInfo& unitObjInfo = *(*iter)->unitObjInfo;
366 TRY(LinkLocalCisaObjInfos(unitObjInfo, localUnitClosuresList));
367 }
368
369 _pendingExternClosures.clear();
370
371 return 0;
372 }
373
374 int
LinkInDepUnits(CompiledUnitClosure & cisaUnitClosure)375 CISALinker::LinkInDepUnits(CompiledUnitClosure& cisaUnitClosure)
376 {
377 CompiledUnitInfo& cisaUnitInfo = *cisaUnitClosure.unit;
378 int globalStartIndex =
379 cisaUnitClosure.unitObjInfo->hdr.num_extern_functions;
380 int staticStartIndex =
381 globalStartIndex +
382 cisaUnitClosure.unitObjInfo->hdr.num_global_functions;
383
384 for (int i = 0; i < cisaUnitInfo.function_reloc_symtab.num_syms; i++) {
385 int inputRefIndex =
386 cisaUnitInfo.function_reloc_symtab.reloc_syms[i].resolved_index;
387
388 if (inputRefIndex >= staticStartIndex) {
389
390 if (CLOSURE(_localUnitMap[inputRefIndex]) == NULL) {
391 CompiledUnitClosure *depUnitClosure =
392 (CompiledUnitClosure *)
393 _mem.alloc(sizeof(CompiledUnitClosure));
394 CLOSURE(_localUnitMap[inputRefIndex]) = depUnitClosure;
395 depUnitClosure->unit =
396 &cisaUnitClosure.unitObjInfo->hdr.functions[inputRefIndex];
397 depUnitClosure->unitObjInfo = cisaUnitClosure.unitObjInfo;
398 depUnitClosure->linkedUnitIndex = _countLinkedUnits++;
399 _linkedUnitIndexToClosureMap.push_back(depUnitClosure);
400 _pendingLocalClosures.push_back(depUnitClosure);
401 }
402 }
403 else if (inputRefIndex >= globalStartIndex) {
404 CompiledUnitClosure *depUnitClosure =
405 UNITCLOSURE(_localUnitMap[inputRefIndex]);
406 INTERNAL_ASSERT(depUnitClosure);
407
408 if (depUnitClosure->linkedUnitIndex == -1) {
409 depUnitClosure->linkedUnitIndex = _countLinkedUnits++;
410 _linkedUnitIndexToClosureMap.push_back(depUnitClosure);
411 _pendingLocalClosures.push_back(depUnitClosure);
412 }
413 }
414 else {
415 CompiledUnitInfo& unit =
416 cisaUnitClosure.unitObjInfo->hdr.functions[inputRefIndex];
417 CompiledUnitClosure *externUnitClosure = NULL;
418 std::string unitName(unit.name, unit.name_len);
419 TRY(GetGlobalUnitClosure(unitName, externUnitClosure));
420
421 if (externUnitClosure->linkedUnitIndex == -1) {
422 externUnitClosure->linkedUnitIndex = _countLinkedUnits++;
423 _linkedUnitIndexToClosureMap.push_back(externUnitClosure);
424 _pendingExternClosures.push_back(externUnitClosure);
425 }
426 }
427 }
428
429 return 0;
430 }
431
432 int
LinkInDepVars(CompiledUnitClosure & cisaUnitClosure)433 CISALinker::LinkInDepVars(CompiledUnitClosure& cisaUnitClosure)
434 {
435 CompiledVarInfo *vars =
436 cisaUnitClosure.unitObjInfo->hdr.filescope_variables;
437 CompiledUnitInfo& cisaUnitInfo = *cisaUnitClosure.unit;
438 int globalStartIndex =
439 cisaUnitClosure.unitObjInfo->hdr.num_extern_variables;
440 int staticStartIndex =
441 globalStartIndex +
442 cisaUnitClosure.unitObjInfo->hdr.num_global_variables;
443
444 for (int i = 0; i < cisaUnitInfo.variable_reloc_symtab.num_syms; i++) {
445 int inputRefIndex =
446 cisaUnitInfo.variable_reloc_symtab.reloc_syms[i].resolved_index;
447
448 if (inputRefIndex >= staticStartIndex) {
449
450 if (CLOSURE(_localVarMap[inputRefIndex]) == NULL) {
451 CompiledVarClosure * depVarClosure =
452 (CompiledVarClosure *)
453 _mem.alloc(sizeof(CompiledVarClosure));
454 CLOSURE(_localVarMap[inputRefIndex]) = depVarClosure;
455 CompiledVarInfo& var = vars[inputRefIndex];
456 depVarClosure->var =&var;
457 depVarClosure->varObjInfo = cisaUnitClosure.unitObjInfo;
458 depVarClosure->linkedVarIndex = _countLinkedVars++;
459 _linkedVarIndexToClosureMap.push_back(depVarClosure);
460 }
461 }
462 else if (inputRefIndex >= globalStartIndex) {
463 CompiledVarClosure *depVarClosure =
464 VARCLOSURE(_localVarMap[inputRefIndex]);
465 INTERNAL_ASSERT(depVarClosure);
466
467 if (depVarClosure->linkedVarIndex == -1) {
468 depVarClosure->linkedVarIndex = _countLinkedVars++;
469 _linkedVarIndexToClosureMap.push_back(depVarClosure);
470 }
471 }
472 else {
473 CompiledVarInfo& variable = vars[inputRefIndex];
474 CompiledVarClosure *externVarClosure = NULL;
475 std::string varName((char *) variable.name, variable.name_len);
476 TRY(GetGlobalVarClosure(varName, externVarClosure));
477
478 if (externVarClosure->linkedVarIndex == -1) {
479 externVarClosure->linkedVarIndex = _countLinkedVars++;
480 _linkedVarIndexToClosureMap.push_back(externVarClosure);
481 }
482 }
483 }
484
485 return 0;
486 }
487
488 int
RelocFunctionSyms(CompiledUnitClosure & localUnitClosure)489 CISALinker::RelocFunctionSyms(CompiledUnitClosure& localUnitClosure)
490 {
491 CompiledUnitInfo& localUnitInfo = *localUnitClosure.unit;
492
493 for (int i = 0; i < localUnitInfo.function_reloc_symtab.num_syms; i++) {
494 int inputRefIndex =
495 localUnitInfo.function_reloc_symtab.reloc_syms[i].resolved_index;
496 int offset = localUnitClosure.unitObjInfo->hdr.num_extern_functions;
497
498 if (inputRefIndex >= offset) {
499 int linkedUnitIndex =
500 UNITCLOSURE(_localUnitMap[inputRefIndex])->linkedUnitIndex;
501 INTERNAL_ASSERT(linkedUnitIndex >= 0);
502 localUnitInfo.function_reloc_symtab.reloc_syms[i].resolved_index =
503 linkedUnitIndex;
504 }
505 else {
506 CompiledUnitInfo *units =
507 localUnitClosure.unitObjInfo->hdr.functions;
508 CompiledUnitInfo& unit = units[inputRefIndex];
509 CompiledUnitClosure *externUnitClosure = NULL;
510 std::string unitName(unit.name, unit.name_len);
511 TRY(GetGlobalUnitClosure(unitName, externUnitClosure));
512 int linkedUnitIndex = externUnitClosure->linkedUnitIndex;
513 INTERNAL_ASSERT(linkedUnitIndex >= 0);
514 localUnitInfo.function_reloc_symtab.reloc_syms[i].resolved_index =
515 linkedUnitIndex;
516 }
517 }
518
519 return 0;
520 }
521
522 int
RelocVariableSyms(CompiledUnitClosure & localUnitClosure)523 CISALinker::RelocVariableSyms(CompiledUnitClosure& localUnitClosure)
524 {
525 CompiledUnitInfo& localUnitInfo = *localUnitClosure.unit;
526 CompiledVarInfo *vars =
527 (CompiledVarInfo *)
528 localUnitClosure.unitObjInfo->hdr.filescope_variables;
529
530 for (int i = 0; i < localUnitInfo.variable_reloc_symtab.num_syms; i++) {
531 int inputRefIndex =
532 localUnitInfo.variable_reloc_symtab.reloc_syms[i].resolved_index;
533 int offset =
534 localUnitClosure.unitObjInfo->hdr.num_extern_variables;
535
536 if (inputRefIndex >= offset) {
537 int linkedVarIndex =
538 VARCLOSURE(_localVarMap[inputRefIndex])->linkedVarIndex;
539 INTERNAL_ASSERT(linkedVarIndex >= 0);
540 localUnitInfo.variable_reloc_symtab.reloc_syms[i].resolved_index =
541 linkedVarIndex;
542 }
543 else {
544 CompiledVarInfo& variable = vars[inputRefIndex];
545 CompiledVarClosure * externVarClosure = NULL;
546 std::string unitName((char *) variable.name, variable.name_len);
547 TRY(GetGlobalVarClosure(unitName, externVarClosure));
548 int linkedVarIndex = externVarClosure->linkedVarIndex;
549 INTERNAL_ASSERT(linkedVarIndex >= 0);
550 localUnitInfo.variable_reloc_symtab.reloc_syms[i].resolved_index =
551 externVarClosure->linkedVarIndex;
552 }
553 }
554
555 return 0;
556 }
557
558 int
BuildLinkedCisaObj(CompiledUnitClosureList & knlClosureList)559 CISALinker::BuildLinkedCisaObj(CompiledUnitClosureList& knlClosureList)
560 {
561 CisaObjInfo& linkedObjInfo = _cisaObjInfos[_numCisaObjInfos];
562 const CisaHeader& firstKnlHdr = knlClosureList.front()->unitObjInfo->hdr;
563
564 linkedObjInfo.hdr.magic_number = firstKnlHdr.magic_number;
565 linkedObjInfo.hdr.major_version = firstKnlHdr.major_version;
566 linkedObjInfo.hdr.minor_version = firstKnlHdr.minor_version;
567 linkedObjInfo.hdr.num_kernels = knlClosureList.size();
568 linkedObjInfo.hdr.num_extern_variables = 0;
569 linkedObjInfo.hdr.num_global_variables = 0;
570 linkedObjInfo.hdr.num_static_variables = _countLinkedVars;
571 linkedObjInfo.hdr.num_filescope_variables = _countLinkedVars;
572 linkedObjInfo.hdr.num_extern_functions = 0;
573 linkedObjInfo.hdr.num_global_functions = 0;
574 linkedObjInfo.hdr.num_static_functions = _countLinkedUnits;
575 linkedObjInfo.hdr.num_functions = _countLinkedUnits;
576 linkedObjInfo.hdr.kernels =
577 (CompiledUnitInfo *)
578 _mem.alloc(sizeof(CompiledUnitInfo) * knlClosureList.size());
579 ALLOC_ASSERT(linkedObjInfo.hdr.kernels);
580 linkedObjInfo.hdr.filescope_variables =
581 (CompiledVarInfo *) _mem.alloc(
582 sizeof(CompiledUnitInfo) * _countLinkedVars);
583
584 if (_countLinkedUnits) {
585 linkedObjInfo.hdr.functions =
586 (CompiledUnitInfo *) _mem.alloc(
587 sizeof(CompiledUnitInfo) * _countLinkedUnits);
588 ALLOC_ASSERT(_countLinkedUnits == 0 || linkedObjInfo.hdr.functions);
589 }
590 else {
591 linkedObjInfo.hdr.functions = NULL;
592 }
593
594 TRY(BuildLinkedVarInfo(linkedObjInfo.hdr));
595 CompiledUnitClosureList::iterator iter = knlClosureList.begin();
596
597 for (int i = 0; iter != knlClosureList.end(); ++iter, ++i) {
598 CompiledUnitClosure& knlClosure = **iter;
599 CompiledUnitInfo& knlInfo = *knlClosure.unit;
600 std::string knlName(knlInfo.name, knlInfo.name_len);
601 TRY(BuildLinkedUnitInfo(
602 knlName, knlClosure, linkedObjInfo.hdr.kernels[i]));
603 }
604
605 for (int i = 0; i < _countLinkedUnits; i++) {
606 CompiledUnitClosure& funcClosure = *_linkedUnitIndexToClosureMap[i];
607 CompiledUnitInfo& funcInfo = *funcClosure.unit;
608 std::string unitName(funcInfo.name, funcInfo.name_len);
609 TRY(BuildLinkedUnitInfo(
610 unitName, funcClosure,linkedObjInfo.hdr.functions[i]));
611 }
612
613 linkedObjInfo.buf = NULL;
614 linkedObjInfo.size = 0;
615
616 return 0;
617 }
618
619 int
BuildLinkedUnitInfo(const std::string & unitName,CompiledUnitClosure & objUnitClosure,CompiledUnitInfo & linkedUnitInfo)620 CISALinker::BuildLinkedUnitInfo(
621 const std::string &unitName, CompiledUnitClosure& objUnitClosure,
622 CompiledUnitInfo& linkedUnitInfo)
623 {
624 CompiledUnitInfo& objUnit = *objUnitClosure.unit;
625
626 linkedUnitInfo.name_len = unitName.size();
627 strncpy(linkedUnitInfo.name, unitName.c_str(), unitName.size());
628 linkedUnitInfo.offset = objUnit.offset;
629 linkedUnitInfo.size = objUnit.size;
630 linkedUnitInfo.input_offset = objUnit.input_offset;
631 BuildRelocSymTab(
632 linkedUnitInfo.variable_reloc_symtab, objUnit.variable_reloc_symtab);
633 BuildRelocSymTab(
634 linkedUnitInfo.function_reloc_symtab, objUnit.function_reloc_symtab);
635 linkedUnitInfo.num_gen_binaries = 0;
636 linkedUnitInfo.cisa_binary_buffer =
637 (char *) objUnitClosure.unitObjInfo->buf + objUnit.offset;
638
639 return 0;
640 }
641
642 int
BuildRelocSymTab(RelocTab & dst,RelocTab & src)643 CISALinker::BuildRelocSymTab(RelocTab& dst, RelocTab& src)
644 {
645 dst.num_syms = src.num_syms;
646
647 if (dst.num_syms) {
648 dst.reloc_syms =
649 (reloc_sym *) _mem.alloc(sizeof(reloc_sym) * src.num_syms);
650 ALLOC_ASSERT(dst.reloc_syms);
651
652 for (int i = 0; i < src.num_syms; i++) {
653 dst.reloc_syms[i].symbolic_index =
654 src.reloc_syms[i].symbolic_index;
655 dst.reloc_syms[i].resolved_index =
656 src.reloc_syms[i].resolved_index;
657 }
658 }
659 else {
660 dst.reloc_syms = NULL;
661 }
662
663 return 0;
664 }
665
666 int
BuildLinkedVarInfo(CisaHeader & linkedUnitHdr)667 CISALinker::BuildLinkedVarInfo(CisaHeader& linkedUnitHdr)
668 {
669 for (int i = 0; i < _countLinkedVars; i++) {
670 CompiledVarInfo& objVariable = *_linkedVarIndexToClosureMap[i]->var;
671 CompiledVarInfo& linkedVariable = linkedUnitHdr.filescope_variables[i];
672 linkedVariable.name_len = objVariable.name_len;
673 linkedVariable.name = objVariable.name;
674 linkedVariable.bit_properties = objVariable.bit_properties;
675 linkedVariable.num_elements = objVariable.num_elements;
676 linkedVariable.attribute_count = objVariable.attribute_count;
677 linkedVariable.attributes = objVariable.attributes;
678 }
679
680 return 0;
681 }
682
683 int
UpdateLinkedCisaImageOffsetsAndSize()684 CISALinker::UpdateLinkedCisaImageOffsetsAndSize()
685 {
686 CisaObjInfo& linkedObjInfo = _cisaObjInfos[_numCisaObjInfos];
687 CisaHeader& linkedObjHdr = linkedObjInfo.hdr;
688
689 _linkedCisaImageSize = 0;
690 _linkedCisaImageSize += sizeof(linkedObjHdr.magic_number);
691 _linkedCisaImageSize += sizeof(linkedObjHdr.major_version);
692 _linkedCisaImageSize += sizeof(linkedObjHdr.minor_version);
693 _linkedCisaImageSize += sizeof(linkedObjHdr.num_kernels);
694
695 for (int i = 0; i < linkedObjHdr.num_kernels; i++) {
696 _linkedCisaImageSize += CalculateSize(linkedObjHdr.kernels[i], false);
697 }
698
699 _linkedCisaImageSize += sizeof(linkedObjHdr.num_filescope_variables);
700
701 for (int i = 0; i < linkedObjHdr.num_filescope_variables; i++) {
702 _linkedCisaImageSize +=
703 CalculateSize(linkedObjHdr.filescope_variables[i]);
704 }
705
706 _linkedCisaImageSize += sizeof(linkedObjHdr.num_functions);
707
708 for (int i = 0; i < linkedObjHdr.num_functions; i++) {
709 _linkedCisaImageSize += CalculateSize(linkedObjHdr.functions[i], true);
710 }
711
712 for (int i = 0; i < linkedObjHdr.num_kernels; i++) {
713 CompiledUnitInfo& knlUnitInfo = linkedObjHdr.kernels[i];
714 unsigned knlUnitDataStartOffset = _linkedCisaImageSize;
715 knlUnitInfo.input_offset = knlUnitInfo.input_offset - knlUnitInfo.offset + knlUnitDataStartOffset;
716 knlUnitInfo.offset = knlUnitDataStartOffset;
717 _linkedCisaImageSize += knlUnitInfo.size;
718 }
719
720 for (int i = 0; i < linkedObjHdr.num_functions; i++) {
721 CompiledUnitInfo& unitInfo = linkedObjHdr.functions[i];
722 unsigned unitDataStartOffset = _linkedCisaImageSize;
723 unitInfo.offset = unitDataStartOffset;
724 _linkedCisaImageSize += unitInfo.size;
725 }
726
727 linkedObjInfo.size = _linkedCisaImageSize;
728
729 return 0;
730 }
731
732 int
CalculateSize(CompiledUnitInfo & unit,bool isFunction)733 CISALinker::CalculateSize(CompiledUnitInfo& unit, bool isFunction)
734 {
735 unsigned size = 0;
736 if( isFunction == true )
737 {
738 size += sizeof(unit.linkage);
739 }
740
741 size += sizeof(unit.name_len) + unit.name_len;
742 size += sizeof(unit.offset);
743 size += sizeof(unit.size);
744
745 if( isFunction == false )
746 {
747 size += sizeof(unit.input_offset);
748 }
749
750 size += CalculateSize(unit.variable_reloc_symtab);
751 size += CalculateSize(unit.function_reloc_symtab);
752
753 if( isFunction == false )
754 {
755 size += sizeof(unit.num_gen_binaries);
756 }
757
758 return size;
759 }
760
761 int
CalculateSize(CompiledVarInfo & var)762 CISALinker::CalculateSize(CompiledVarInfo& var)
763 {
764 unsigned size = 0;
765 size += sizeof(var.linkage);
766 size += sizeof(var.name_len) + var.name_len;
767 size += sizeof(var.bit_properties);
768 size += sizeof(var.num_elements);
769 size += sizeof(var.attribute_count);
770
771 for (int i = 0; i < var.attribute_count; i++) {
772 size += sizeof(var.attributes[i].nameIndex);
773 size +=
774 sizeof(var.attributes[i].size) + var.attributes[i].size;
775 }
776
777 return size;
778 }
779
780 int
CalculateSize(RelocTab & symTab)781 CISALinker::CalculateSize(RelocTab& symTab)
782 {
783 unsigned size = 0;
784 size += sizeof(symTab.num_syms);
785 size += sizeof(reloc_sym) * symTab.num_syms;
786
787 return size;
788 }
789
790 int
AllocateCisaObjInfos(int numCisaObjs)791 CISALinker::AllocateCisaObjInfos(int numCisaObjs)
792 {
793 _cisaObjInfos =
794 (CisaObjInfo *)_mem.alloc(sizeof(CisaObjInfo) * (numCisaObjs + 1));
795 ALLOC_ASSERT(_cisaObjInfos);
796 _numCisaObjInfos = numCisaObjs;
797
798 for (int i = 0; i < numCisaObjs + 1; i++) {
799 _cisaObjInfos[i].index = i;
800 }
801
802 return 0;
803 }
804
805 int
ReadCisaMemObj(const CisaObj & cisaObj,CisaObjInfo & cisaObjInfo)806 CISALinker::ReadCisaMemObj(const CisaObj& cisaObj, CisaObjInfo& cisaObjInfo)
807 {
808 unsigned cisaBytePos = 0;
809
810 if (ExtractCisaMemObjHdr(cisaObjInfo.hdr, cisaBytePos, cisaObj.buf)) {
811 return 1;
812 }
813
814 ASSERT(cisaBytePos <= cisaObj.size, "Corrupted CISA object");
815 cisaObjInfo.buf = cisaObj.buf;
816 cisaObjInfo.size = cisaObj.size;
817
818 return 0;
819 }
820
821
822 inline int
ExtractCisaMemObjHdr(CisaHeader & cisaHdr,unsigned & cisaBytePos,const void * cisaBuffer)823 CISALinker::ExtractCisaMemObjHdr(
824 CisaHeader& cisaHdr, unsigned& cisaBytePos, const void *cisaBuffer)
825 {
826 TRY(::processCommonISAHeader(cisaHdr, cisaBytePos, cisaBuffer, &_mem));
827 ASSERT(
828 cisaHdr.major_version >= 3, "Linking is supported only for CISA 3.0+");
829
830 return 0;
831 }
832
833 int
ReadCisaFileObj(const char * cisaFileName,CisaObjInfo & cisaObjInfo)834 CISALinker::ReadCisaFileObj(const char *cisaFileName, CisaObjInfo& cisaObjInfo)
835 {
836 FILE *cisaFile = fopen(cisaFileName, "rb");
837 ASSERT(cisaFile != NULL, "Cannot open %s", cisaFileName);
838 fseek(cisaFile, 0, SEEK_END);
839 unsigned fileSize = ftell(cisaFile);
840 char *cisaBuffer = (char *) _mem.alloc(fileSize);
841 fseek(cisaFile, 0, SEEK_SET);
842 ALLOC_ASSERT(cisaBuffer);
843 ASSERT(
844 fread(cisaBuffer, 1, fileSize, cisaFile) != 0,
845 "Cannot read CISA object %s", cisaFileName);
846 fclose(cisaFile);
847 CisaObj cisaObj;
848 cisaObj.buf = cisaBuffer;
849 cisaObj.size = fileSize;
850
851 return ReadCisaMemObj(cisaObj, cisaObjInfo);
852 }
853
854 int
WriteCisaMemObj(CisaObj & cisaObj)855 CISALinker::WriteCisaMemObj(CisaObj& cisaObj)
856 {
857 TRY(WriteCisaMemObj());
858 cisaObj.size = _linkedCisaImageSize;
859 cisaObj.buf = (char *) (*_allocator)(_linkedCisaImageSize);
860 CisaObjInfo& linkedObjInfo = _cisaObjInfos[_numCisaObjInfos];
861 memcpy((void *) cisaObj.buf, linkedObjInfo.buf, cisaObj.size);
862 ALLOC_ASSERT(cisaObj.buf);
863
864 return 0;
865 }
866
867 int
WriteCisaMemObj()868 CISALinker::WriteCisaMemObj()
869 {
870 CisaObjInfo& linkedObjInfo = _cisaObjInfos[_numCisaObjInfos];
871 CisaHeader& linkedObjHdr = linkedObjInfo.hdr;
872 CompiledUnitInfo& knlUnitInfo = linkedObjHdr.kernels[0];
873
874 linkedObjInfo.size = _linkedCisaImageSize;
875 linkedObjInfo.buf = (char *) _mem.alloc(_linkedCisaImageSize);
876 ALLOC_ASSERT(linkedObjInfo.buf);
877
878 BUF_APPEND_SCALAR(linkedObjHdr.magic_number);
879 BUF_APPEND_SCALAR(linkedObjHdr.major_version);
880 BUF_APPEND_SCALAR(linkedObjHdr.minor_version);
881 BUF_APPEND_SCALAR(linkedObjHdr.num_kernels);
882
883 for (int i = 0; i < linkedObjHdr.num_kernels; i++) {
884 WriteCisaCompiledUnitInfo(linkedObjHdr.kernels[i], false);
885 }
886
887 BUF_APPEND_SCALAR(linkedObjHdr.num_filescope_variables);
888
889 for (int i = 0; i < linkedObjHdr.num_filescope_variables; i++) {
890 WriteCisaVarInfo(linkedObjHdr.filescope_variables[i]);
891 }
892
893 BUF_APPEND_SCALAR(linkedObjHdr.num_functions);
894 for (int i = 0; i < linkedObjHdr.num_functions; i++) {
895 WriteCisaCompiledUnitInfo(linkedObjHdr.functions[i], true);
896 }
897
898 for (int i = 0; i < linkedObjHdr.num_kernels; i++) {
899 WriteCisaCompiledUnitData(linkedObjHdr.kernels[i]);
900 }
901
902 for (int i = 0; i < linkedObjHdr.num_functions; i++) {
903 WriteCisaCompiledUnitData(linkedObjHdr.functions[i]);
904 }
905
906 INTERNAL_ASSERT(linkedObjInfo.size == _linkedCisaImageSize);
907
908 return 0;
909 }
910
911 int
WriteCisaCompiledUnitInfo(CompiledUnitInfo & unit,bool isFunction)912 CISALinker::WriteCisaCompiledUnitInfo(CompiledUnitInfo& unit, bool isFunction)
913 {
914 if( isFunction == true )
915 {
916 BUF_APPEND_SCALAR(unit.linkage);
917 }
918
919 BUF_APPEND_SCALAR(unit.name_len);
920 BUF_APPEND_VECTOR(unit.name, unit.name_len);
921 BUF_APPEND_SCALAR(unit.offset);
922 BUF_APPEND_SCALAR(unit.size);
923
924 if( isFunction == false )
925 {
926 BUF_APPEND_SCALAR(unit.input_offset);
927 }
928
929 WriteRelocSymTab(unit.variable_reloc_symtab);
930 WriteRelocSymTab(unit.function_reloc_symtab);
931
932 if( isFunction == false )
933 {
934 unit.num_gen_binaries = 0;
935 BUF_APPEND_SCALAR(unit.num_gen_binaries);
936 }
937
938 return 0;
939 }
940
941 int
WriteCisaVarInfo(CompiledVarInfo & var)942 CISALinker::WriteCisaVarInfo(CompiledVarInfo& var)
943 {
944 BUF_APPEND_SCALAR(var.linkage);
945 BUF_APPEND_SCALAR(var.name_len);
946 BUF_APPEND_VECTOR(var.name, var.name_len);
947 BUF_APPEND_SCALAR(var.bit_properties);
948 BUF_APPEND_SCALAR(var.num_elements);
949 BUF_APPEND_SCALAR(var.attribute_count);
950
951 for (int i = 0; i < var.attribute_count; i++) {
952 BUF_APPEND_SCALAR(var.attributes[i].nameIndex);
953 BUF_APPEND_SCALAR(var.attributes[i].size);
954 BUF_APPEND_VECTOR(
955 var.attributes[i].value.stringVal, var.attributes[i].size);
956 }
957
958 return 0;
959 }
960
961 int
WriteRelocSymTab(RelocTab & symTab)962 CISALinker::WriteRelocSymTab(RelocTab& symTab)
963 {
964 BUF_APPEND_SCALAR(symTab.num_syms);
965
966 for (int i = 0; i < symTab.num_syms; i++) {
967 BUF_APPEND_SCALAR(symTab.reloc_syms[i].symbolic_index);
968 BUF_APPEND_SCALAR(symTab.reloc_syms[i].resolved_index);
969 }
970
971 return 0;
972 }
973
974 int
WriteCisaCompiledUnitData(CompiledUnitInfo & unitInfo)975 CISALinker::WriteCisaCompiledUnitData(CompiledUnitInfo& unitInfo)
976 {
977 if (unitInfo.size) {
978 BUF_APPEND_VECTOR(unitInfo.cisa_binary_buffer, unitInfo.size);
979 }
980
981 return 0;
982 }
983
984 int
WriteCisaFileObj(const char * cisaFileName)985 CISALinker::WriteCisaFileObj(const char *cisaFileName)
986 {
987 WriteCisaMemObj();
988 FILE *cisaFile = fopen(cisaFileName, "wb");
989 ASSERT(cisaFile != NULL, "Cannot open %s for write", cisaFileName);
990 CisaObjInfo& cisaObjInfo = _cisaObjInfos[_numCisaObjInfos];
991 ASSERT(
992 fwrite(cisaObjInfo.buf, 1, cisaObjInfo.size, cisaFile) ==
993 cisaObjInfo.size,
994 "Error in writing linked CISA object");
995 fclose(cisaFile);
996
997 return 0;
998 }
999