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 /*
10  * The IGA - Intel Gen Assembler external C API
11  */
12 #ifndef IGA_H
13 #define IGA_H
14 
15 #include "iga_types_swsb.hpp"
16 
17 #include <stdint.h>
18 #include <stddef.h>
19 #ifdef _WIN32
20 #include <crtdefs.h>
21 #endif
22 
23 #ifdef _WIN32
24 #ifdef IGA_BUILDING_DLL
25 #define IGA_API __declspec(dllexport)
26 /* define this symbol if you wish to statically link against iga32.dll */
27 #elif IGA_DLL_IMPORT
28 #define IGA_API __declspec(dllimport)
29 #else
30 #define IGA_API
31 #endif
32 #else
33     #if __GNUC__ >= 4
34         #define IGA_API __attribute__ ((visibility ("default")))
35     #else
36 #define IGA_API
37     #endif
38 #endif
39 
40 #ifdef __cplusplus
41 extern "C"  {
42 #endif
43 
44 /* opaque pointer to context type */
45 typedef void *iga_context_t;
46 
47 typedef enum {
48     IGA_SUCCESS        = 0, /* the operation completed successfully
49                              * (iga_disassemble and iga_assemble may
50                              * still have logged warnings) */
51     IGA_ERROR          = 1, /* general error */
52     IGA_INVALID_ARG    = 2, /* something wrong with an arugment */
53     IGA_OUT_OF_MEM     = 3, /* failed to allocate */
54     IGA_DECODE_ERROR   = 4, /* error during decode phase */
55     IGA_ENCODE_ERROR   = 5, /* error during the encode phase */
56     IGA_PARSE_ERROR    = 6, /* error duing the parse phase (syntax) */
57     IGA_VERSION_ERROR  = 7, /* this header file is newer than the binary
58                              * called */
59     IGA_INVALID_OBJECT = 8, /* attempt to use an destroyed object
60                              * (e.g. iga_context_t) */
61     IGA_INVALID_STATE  = 9, /* e.g. call to iga_get_errors before disassembly*/
62     IGA_UNSUPPORTED_PLATFORM = 10, /* platform not supported with this binary */
63     IGA_DIFF_FAILURE = 11 /* used by -Xifs for diffing instructions */
64 } iga_status_t;
65 
66 /*
67  * Converts an IGA status string code to a human-readable string.
68  *
69  * RETURNS: IGA_SUCCESS
70  */
71 IGA_API const char *iga_status_to_string(iga_status_t st);
72 
73 
74 /*
75 * Returns a NUL-terminated version string corresponding to the version of
76 * IGA.
77 */
78 IGA_API const char *iga_version_string();
79 
80 
81 /* The encoding for GEN version enumerates follows this pattern */
82 #define GEN_VER(MAJ,MIN) (((MAJ)<<16)|(MIN))
83 
84 /* The encoding for XE version enumerates follows this pattern
85 * All XE_VER() must be larger than GEN_VER().  XE_VER(0,*) is illegal. TGL is XE_VER(1,0)
86 */
87 #define XE_VER(MAJ,MIN) (((MAJ)<<24)|(MIN))
88 
89 
90 /* Represents the specific version of Gen being assembled or disassembled */
91 typedef enum {
92     IGA_GEN_INVALID = 0
93   , IGA_GEN7      = GEN_VER(7,0)
94   , IGA_GEN7p5    = GEN_VER(7,5)
95   , IGA_GEN8      = GEN_VER(8,0)
96   , IGA_GEN8lp    = GEN_VER(8,1)
97   , IGA_GEN9      = GEN_VER(9,0)
98   , IGA_GEN9lp    = GEN_VER(9,1)
99   , IGA_GEN9p5    = GEN_VER(9,5)
100   , IGA_GEN10     = GEN_VER(10,0)
101   , IGA_GEN11     = GEN_VER(11,0)
102   // XE versions
103   , IGA_XE        = XE_VER(1, 0) // TGL
104   , IGA_XE_HP     = XE_VER(1, 1)
105   , IGA_XE_HPG    = XE_VER(1, 2)
106   , IGA_XE_HPC    = XE_VER(1, 4)
107 
108   // TO BE DEPRECATED
109   // Preserve the old values to maintain the binary compatibility
110   // The value should not be used anymore
111   , IGA_GEN12p1  = GEN_VER(12,1)  // IGA_XE
112 } iga_gen_t;
113 
114 
115 /*****************************************************************************/
116 /*                     Platform Query Functions                              */
117 /*****************************************************************************/
118 
119 /*
120  * Returns a list of the platforms enumeration values supported by this
121  * implementation of IGA into a user-provided buffer.  The buffer parameter
122  * maybe omitted.
123  *
124  * PARAMETERS:
125  *  gens_length_bytes            the length of the gens buffer in bytes;
126  *                               can be 0 if gens is NULL
127  *  gens                         the user-provided buffer (can be NULL);
128  *                               if non-NULL, the output will contain the list
129  *                               of iga_gen_t platforms that this IGA supports
130  *  gens_length_bytes_required   the required length
131  *
132  * RETURNS:
133  *   IGA_INVALID_ARGUMENT  if gens_length_bytes != 0 && gens == nullptr
134  *   IGA_SUCCESS           otherwise
135  */
136 IGA_API iga_status_t iga_platforms_list(
137   size_t gens_length_bytes,
138   iga_gen_t *gens,
139   size_t *gens_length_bytes_required);
140 /*
141  * Returns the platform suffix name of a given platform.
142  *
143  * PARAMETERS:
144  *  gen                   the platform to query
145  *  suffix                an output parameter assigned the result;
146  *                        NULL is assigned if the 'gen' passed in is invalid
147  *                        or unsupported
148  *
149  * RETURNS:
150  *   IGA_INVALID_ARGUMENT  if symbol is NULL or 'gen' is invalid or not
151  *                         supported by this platform
152  *   IGA_SUCCESS           otherwise
153  */
154 IGA_API iga_status_t iga_platform_symbol_suffix(
155     iga_gen_t gen,
156     const char **suffix);
157 /*
158  * Returns the names for a given platform.  E.g. IGA_GEN9 returns "skl".
159  *
160  * PARAMETERS:
161  *  gen                   the platform to query
162  *  names_bytes           the length in bytes of the names array passed in
163  *                        0 iff 'names' is nullptr
164  *  names                 the array to return the platform names in
165  *  names_bytes_needed    the required length of 'names' in bytes
166  *
167  * RETURNS:
168  *   IGA_INVALID_ARGUMENT  if gen is an invalid platform
169  *                         supported by this platform
170  *   IGA_INVALID_ARGUMENT  if names_bytes != 0 && names == nullptr
171  *   IGA_SUCCESS           otherwise
172  */
173 IGA_API iga_status_t iga_platform_names(
174     iga_gen_t gen,
175     size_t names_bytes,
176     const char **names,
177     size_t *names_bytes_needed);
178 
179 
180 
181 /*****************************************************************************/
182 /*                  Context Creation Functions                               */
183 /*****************************************************************************/
184 
185 /*
186  * Context options
187  */
188 typedef struct {
189     size_t        cb;   /* set to sizeof(iga_context_options_t) */
190     iga_gen_t     gen;
191 } iga_context_options_t;
192 /* this is an ugly wart, cb should have been uint32_t *
193  * TODO: change this in IGA 2.0 and break binary compatibility there*/
194 
195 /*
196  * This macro initializes options to the context.
197  *  iga_gen_t   P    the gen platform to use
198  */
199 #define IGA_CONTEXT_OPTIONS_INIT(P) \
200     {sizeof(iga_context_options_t), (P)}
201 
202 
203 /*
204  * Creates a context, which is needed to assemble and disassemble kernels.
205  * A context manages internal dynamically allocated memory containing
206  * the diagnostics.
207  *
208  * PARAMETERS:
209  *  opts         the options to this iga context
210  *  ctx          points to the newly created context
211  *
212  * RETURNS:
213  *  IGA_SUCCESS           upon successful context creation
214  *  IGA_INVALID_ARG       if an argument is NULL
215  *  IGA_INVALID_OBJECT    if ctx has already been destroyed
216  *  IGA_OUT_OF_MEM        upon internal allocation failure
217  *  IGA_INVALID_PLATFORM  if the platform passed is unsupported
218  */
219 IGA_API iga_status_t  iga_context_create(
220     const iga_context_options_t *opts,
221     iga_context_t *ctx);
222 /* deprecated: covers to iga_context_create */
223 IGA_API iga_status_t  iga_create_context(
224     const iga_context_options_t *opts,
225     iga_context_t *ctx);
226 
227 
228 /*
229  * Releases a context previously created via 'iga_context_create'.
230  *
231  * RETURNS:
232  *  IGA_SUCCESS         upon successful context release
233  *  IGA_INVALID_ARG     if an argument is NULL
234  *  IGA_INVALID_OBJECT  if ctx has already been destroyed
235  */
236 IGA_API iga_status_t  iga_context_release(iga_context_t ctx);
237 /* deprecated: covers to iga_context_release */
238 IGA_API iga_status_t  iga_release_context(iga_context_t ctx);
239 
240 
241 /*****************************************************************************/
242 /*                  Assembly Functions                                       */
243 /*****************************************************************************/
244 
245 /*
246  * This structure contains options to the 'iga_assemble' call.
247  */
248 typedef struct {
249     uint32_t     cb;                 /* sizeof(iga_context_options_t)    */
250     uint32_t     enabled_warnings;   /* bitset of IGA_WARNINGS*          */
251     uint32_t     encoder_opts;       /* bitset of IGA_ENCODER_OPT*       */
252     uint32_t     syntax_opts;        /* bitset of IGA_SYNTAX_OPT*        */
253      /* the following must be 0 or a warning is raised */
254     uint32_t     _reserved0;         /* use IGA_ENCODER_OPT_ERRONCOMPACT */
255     uint32_t     _reserved1;         /* use IGA_ENCODER_OPT_AUTODEP      */
256     /*
257      * ... future fields (ensure total size is a multiple of 8;
258      * add "reserved" if needed) ...
259      * do not reuse _reserved0 and _reserved1 since those were
260      * historically something else
261      */
262 
263     // number of sbid used for auto dependency setting. This value is effective
264     // only when IGA_ENCODER_OPT_AUTO_DEPENDENCIES is given
265     uint32_t sbid_count;
266     // force the swsb_encode_mode. If not given, the encode mode will be
267     // derived from platform
268     iga::SWSB_ENCODE_MODE swsb_encode_mode;
269 } iga_assemble_options_t;
270 
271 /* detects screwups where someone adds a field and the compiler pads
272  * the structure out implicitly */
273 static_assert(sizeof(iga_assemble_options_t) == 8*4,
274     "wrong size for iga_assemble_options");
275 
276 
277 /*
278  * encoding options
279  */
280 /*
281  * Automatically compact instructions without explicit compaction annotations.
282  * E.g. with this enabled:
283  *    op (...) ... {Compacted}   // will compact
284  *    op (...) ... { }           // try and compact iff IGA_ENCOPTS_AUTOCOMPACT
285  *    op (...) ... {Uncompacted} // will not attempt to compact
286  */
287 #define IGA_ENCODER_OPT_AUTO_COMPACT            0x00000001u
288 /* auto set instruction dependencies */
289 #define IGA_ENCODER_OPT_AUTO_DEPENDENCIES       0x00000002u
290 /* treat failure to compact an instruction with a {Compacted} annotation
291 * as a hard error rather than just raising a warning */
292 #define IGA_ENCODER_OPT_ERROR_ON_COMPACT_FAIL   0x00000004u
293 /* enable experimental native encoder */
294 #define IGA_ENCODER_OPT_USE_NATIVE              0x00000008u
295 /* forcely NoCompact to all instructions even if {Compacted} is set on the instruction
296    This option will overried IGA_ENCODER_OPT_AUTO_COMPACT */
297 #define IGA_ENCODER_OPT_FORCE_NO_COMPACT        0x00000010u
298 
299 /*
300  * options for the parsing phase
301  */
302 /* nominal support for certain IsaAsm directives and syntax */
303 #define IGA_SYNTAX_OPT_LEGACY_SYNTAX   0x00000001u
304 /* enables syntax extensions */
305 #define IGA_SYNTAX_OPT_EXTENSIONS      0x00000002u
306 
307 
308 /*
309  * extra assemble warnings (things to check)
310  * (for iga_assemble_options_t::enabled_warnings)
311  */
312 /* individual warnings */
313 #define IGA_WARNINGS_REGIONS    0x00000001u  /* -Wregions */
314 #define IGA_WARNINGS_TYPES      0x00000002u  /* -Wtypes */
315 #define IGA_WARNINGS_SCHED      0x00000004u  /* -Wscheduling */
316 #define IGA_WARNINGS_NORMFORM   0x00000008u  /* -Wnormal-form */
317 /* useful predefined sets */
318 #define IGA_WARNINGS_NONE       0x00000000u  /* -Wnone */
319 #define IGA_WARNINGS_ALL \
320     (IGA_WARNINGS_REGIONS|\
321     IGA_WARNINGS_TYPES|\
322     IGA_WARNINGS_SCHED|\
323     IGA_WARNINGS_NORMFORM)  /* -Wall */
324 #define IGA_WARNINGS_DEFAULT \
325     (IGA_WARNINGS_REGIONS|\
326     IGA_WARNINGS_SCHED) /* -Wdefault */
327 
328 /* helpful initializers for assembly options with good defaults */
329 #define IGA_ASSEMBLE_OPTIONS_INIT() \
330     { \
331       sizeof(iga_assemble_options_t), \
332       IGA_WARNINGS_DEFAULT, \
333       (IGA_ENCODER_OPT_ERROR_ON_COMPACT_FAIL), \
334       0, /* syntax_opts = NONE */ \
335       0, /* reserved */  \
336       0, /* reserved */  \
337       16, /* sbid_count */ \
338       iga::SWSB_ENCODE_MODE::SWSBInvalidMode \
339     }
340 
341 /*
342  * Assembles some text into bits.
343  *
344  * PARAMETERS:
345  *  ctx           the iga context
346  *  opts          the assemble options
347  *  kernel_text   a NUL-terminated string containing the kernel text
348  *                to assemble
349  *  output        the output assembly binary; upon failure, this is
350  *                assigned NULL; this memory should not be modified
351  *                or deallocated externally
352  *  output_size   the length of 'output' (in bytes); assigned 0 upon failure
353  *
354  * RETURNS:
355  *  IGA_SUCCESS         upon successful assembly; 'iga_get_warnings' may
356  *                      contain warning diagnostics even upon success
357  *  IGA_INVALID_ARG     if an argument is NULL
358  *  IGA_INVALID_OBJECT  if ctx has already been destroyed
359  *  IGA_PARSE_ERROR     if the text is somehow malformed and IGA is unable
360  *                      to parse it; use iga_get_errors for more info
361  *  IGA_ENCODE_ERROR    if the encoder encounters some error
362  *                      (use iga_get_errors for more info)
363  *  IGA_ERROR           upon some other error
364  */
365 IGA_API iga_status_t  iga_context_assemble(
366     iga_context_t ctx,
367     const iga_assemble_options_t *opts,
368     const char *kernel_text,
369     void **output,
370     uint32_t *output_size);
371 /* deprecated API covers to iga_contex* */
372 IGA_API iga_status_t  iga_assemble(
373     iga_context_t ctx,
374     const iga_assemble_options_t *opts,
375     const char *kernel_text,
376     void **output,
377     uint32_t *output_size);
378 
379 
380 /*****************************************************************************/
381 /*                  Disassembly Functions                                    */
382 /*****************************************************************************/
383 
384 /*
385  * This structure contains options to the 'iga_disassemble' call.
386  */
387 typedef struct {
388     uint32_t     cb;   /* set to sizeof(iga_context_options_t) */
389     uint32_t     formatting_opts; /* options in formatting the syntax */
390     uint32_t     _reserved0; /* use formatting_opts; set this to 0! */
391     uint32_t     _reserved1; /* use formatting_opts; set this to 0! */
392     uint32_t     decoder_opts; /* opts for the decoding phase */
393     /* ... future fields (ensure total size is a multiple of 8;
394      * add "reserved" if needed) ... */
395 } iga_disassemble_options_t;
396 
397 static_assert(sizeof(iga_disassemble_options_t) == 5*4,
398     "wrong size for iga_disassemble_options_t");
399 
400 /* A default value for iga_disassemble_options_t */
401 #define IGA_DISASSEMBLE_OPTIONS_INIT() \
402     {sizeof(iga_disassemble_options_t), \
403      IGA_FORMATTING_OPTS_DEFAULT, \
404      0, /* _reserved0 */ \
405      0,  /* _reserved1 */ \
406      IGA_DECODING_OPTS_DEFAULT, /* decoder_opts */ }
407 
408 /* A default value for iga_disassemble_options_t that enables numeric labels */
409 #define IGA_DISASSEMBLE_OPTIONS_INIT_NUMERIC_LABELS() \
410     {sizeof(iga_disassemble_options_t), \
411      IGA_FORMATTING_OPTS_DEFAULT|IGA_FORMATTING_OPT_NUMERIC_LABELS, \
412      0, /* _reserved0 */ \
413      0, /* _reserved1 */ \
414      IGA_DECODING_OPTS_DEFAULT, /* decoder_opts */ }
415 
416 /*
417  * options for the formatting phase (the syntax emitted / printed)
418  */
419 /* does not use numeric labels */
420 #define IGA_FORMATTING_OPT_NUMERIC_LABELS   0x00000001u
421 /* enables certain syntax extensions */
422 #define IGA_FORMATTING_OPT_SYNTAX_EXTS      0x00000002u
423 /* force floats to be emitted in hexadecimal */
424 #define IGA_FORMATTING_OPT_PRINT_HEX_FLOATS 0x00000004u
425 /* print the instruction PC's */
426 #define IGA_FORMATTING_OPT_PRINT_PC         0x00000008u
427 /* print the instruction bits */
428 #define IGA_FORMATTING_OPT_PRINT_BITS       0x00000010u
429 /* print immediate instruction dependencies (mostly for IGA debugging) */
430 #define IGA_FORMATTING_OPT_PRINT_DEPS       0x00000020u
431 /* print load/store pseduo instructions where possible */
432 #define IGA_FORMATTING_OPT_PRINT_LDST       0x00000040u
433 /* print bfn symbolic instructions */
434 #define IGA_FORMATTING_OPT_PRINT_BFNEXPRS   0x00000080u
435 /* use ansi_span escapes when possible */
436 #define IGA_FORMATTING_OPT_PRINT_ANSI       0x00000100u
437 /* emit JSON instead of asm */
438 #define IGA_FORMATTING_OPT_PRINT_JSON       0x00000200u
439 /* emit instruction definitions from a simple dataflow analysis */
440 #define IGA_FORMATTING_OPT_PRINT_DEFS       0x00000400u
441 
442 /* just the default formatting opts */
443 #define IGA_FORMATTING_OPTS_DEFAULT \
444     (0u)
445 /* a union of all formatter opts */
446 #define IGA_FORMATTING_OPTS_ALL = \
447     (IGA_FORMATTING_OPT_NUMERIC_LABELS\
448     |IGA_FORMATTING_OPT_SYNTAX_EXTS\
449     |IGA_FORMATTING_OPT_PRINT_HEX_FLOATS\
450     |IGA_FORMATTING_OPT_PRINT_PC\
451     |IGA_FORMATTING_OPT_PRINT_BITS\
452     |IGA_FORMATTING_OPT_PRINT_DEPS\
453     |IGA_FORMATTING_OPT_PRINT_DEFS)
454 
455 /* uses the native decoder for decoding the kernel */
456 #define IGA_DECODING_OPT_NATIVE   0x00000001u
457 /* just the default decoding opts */
458 #define IGA_DECODING_OPTS_DEFAULT \
459     (0u)
460 
461 /*
462  * Disassembles kernel bits into a string.
463  *
464  * PARAMETERS:
465  *  ctx             an iga context
466  *  dopts           the disassemble options
467  *  input           the instructions to disassemble
468  *  input_size      the size of the 'input' in bytes
469  *  fmt_label_name  optional callback to resolve a PC to specific label
470  *                   - if the callback is NULL or the callback returns NULL,
471  *                     then IGA generates the label names
472  *                   - for instructions with multiple labels the caller
473  *                     may reuse any buffers for each label
474  *                   *** PCs are relative to the start of the disassembly  ***
475  *                   *** for this API                                      ***
476  *  fmt_label_ctx   A callback context (environment) forwarded to 'fmt_label'
477  *                  E.g. a buffer to construct the label with
478  *  kernel_text     a pointer containing the NUL-terminate disassembly text;
479  *                  this memory is internally allocated and should not be freed
480  *                  by the user; moreover, it may be invalidated upon the next
481  *                  call using this context (freed or even reused); upon a
482  *                  decoding error this may contain the partially decoded
483  *                  kernel or the empty string if something catestrophic
484  *                  happened, but the pointer returned will always be valid
485  *                  (until the subsequent call)
486  *
487  * RETURNS:
488  *  IGA_SUCCESS         upon successful disassembly; 'iga_get_warnings' may
489  *                      contain warning diagnostics even upon success
490  *  IGA_INVALID_ARG     if an argument is NULL; 'input' may be NULL only
491  *                      if 'input_size' is also 0
492  *  IGA_INVALID_OBJECT  if ctx has already been destroyed
493  *  IGA_DECODE_ERROR    upon failure to decode error; specific error messages
494  *                      may be retrieved via 'iga_context_get_errors'
495  */
496 IGA_API  iga_status_t  iga_context_disassemble(
497     iga_context_t ctx,
498     const iga_disassemble_options_t *opts,
499     const void *input,
500     uint32_t input_size,
501     const char *(*fmt_label_name)(int32_t, void *),
502     void *fmt_label_ctx,
503     char **kernel_text);
504 /* deprecated API covers to iga_context_* */
505 IGA_API  iga_status_t  iga_disassemble(
506     iga_context_t ctx,
507     const iga_disassemble_options_t *opts,
508     const void *input,
509     uint32_t input_size,
510     const char *(*fmt_label_name)(int32_t, void *),
511     void *fmt_label_ctx,
512     char **kernel_text);
513 
514 
515 /*
516  * Disassembles a single instruction.
517  *
518  *  ctx             an iga context
519  *  dopts           the disassemble options
520  *  input           the instructions to disassemble; the first 8-16 bytes
521  *                  must be readable (16 if compaction control is set)
522  *  fmt_label_name  optional callback to resolve a PC to specific label
523  *                   - if the callback is NULL or the callback returns NULL,
524  *                     then IGA generates the label names
525  *                   - for instructions with multiple labels the caller
526  *                     may reuse any buffers for each label
527  *                   *** PCs are relative to the start of this instruction ***
528  *                   *** for this API                                      ***
529  *  fmt_label_ctx   A callback context (environment) forwarded to 'fmt_label'
530  *                  E.g. a buffer to construct the label with
531  *  kernel_text     a pointer containing the NUL-terminate disassembly text;
532  *                  this memory is internally allocated and should not be freed
533  *                  by the user; moreover, it may be invalidated upon the next
534  *                  call using this context (freed or even reused); upon a
535  *                  decoding error this may contain the partially decoded
536  *                  kernel or the empty string if something catestrophic
537  *                  happened, but the pointer returned will always be valid
538  *                  (until the subsequent call)
539  *
540  * RETURNS:
541  *  IGA_SUCCESS         upon successful disassembly; 'iga_get_warnings' may
542  *                      contain warning diagnostics even upon success
543  *  IGA_INVALID_ARG     if an argument is NULL
544  *  IGA_INVALID_OBJECT  if ctx has already been destroyed
545  *  IGA_DECODE_ERROR    upon failure to decode error; specific error messages
546  *                      may be retrieved via 'iga_context_get_errors'
547  */
548 IGA_API  iga_status_t  iga_context_disassemble_instruction(
549     iga_context_t ctx,
550     const iga_disassemble_options_t *dopts,
551     const void *input,
552     const char *(*fmt_label_name)(int32_t, void *),
553     void *fmt_label_ctx,
554     char **kernel_text);
555 /* deprecated API covers to iga_contex* */
556 IGA_API  iga_status_t  iga_disassemble_instruction(
557     iga_context_t ctx,
558     const iga_disassemble_options_t *dopts,
559     const void *input,
560     const char *(*fmt_label_name)(int32_t, void *),
561     void *fmt_label_ctx,
562     char **kernel_text);
563 
564 
565 /*****************************************************************************/
566 /*             Diagnostic Processing Functions                               */
567 /*****************************************************************************/
568 
569 /*
570  * A diagnostic message (e.g. error or warning)
571  *
572  * WARNING: This structure may be made opaque in future releases.
573  *          Treat it as an opaque type and use the accessors to minimize
574  *          any conversion time down the road.
575  */
576 typedef struct {
577     /* lines start at 1; 0 means no location information */
578     uint32_t    line;
579     /* columns start at 1; 0 means no location information */
580     uint32_t    column;
581     /* the input offset */
582     uint32_t    offset;
583     /* the length of the diagnostic (in characters) */
584     uint32_t    extent;
585     /* the diagnostic message (NUL terminated) */
586     const char *message;
587 } iga_diagnostic_t;
588 
589 
590 /*
591  * Gets the errors from previous 'iga_context_assemble' or
592  * 'iga_context_disassmble'.  It is an error to call this before one of these
593  * functions have been called.  Further invocations of this function return
594  * the same values until one of the above functions is called again.  Memory
595  * returned by this function should not be modified externally.  Moreover, it
596  * should not be accessed after the next call to 'iga_context_assemble' or
597  * 'iga_context_disassmble' or the call to 'iga_context_release'.
598  *
599  * PARAMETERS:
600  *   ctx          the iga context used in the call to 'iga_context_assemble'
601  *                or 'iga_context_disassmble'
602  *   ds           assigned to an internally allocated array of diagnostic
603  *                messages (the caller should *not* mutate or free this memory)
604  *   ds_len       assigned the length of 'ds' upon success
605  *
606  * RETURNS:
607  *  IGA_SUCCESS   upon getting the list of errors; note if the last call
608  *                contained no errors, this still returns IGA_SUCCESS;
609  *                'ds' is assigned a NULL pointer and 'ds_len' is assigned 0.
610  *  IGA_INVALID_ARG     if an argument is NULL
611  *  IGA_INVALID_OBJECT  if ctx has already been destroyed
612  *  IGA_ERROR           if 'iga_assemble' or 'iga_disassmble' never called,
613  *                      internal allocation fails, or the context is invalid
614  *                      (after call to 'iga_context_release').
615  */
616 IGA_API iga_status_t iga_context_get_errors(
617     iga_context_t ctx,
618     const iga_diagnostic_t **ds,
619     uint32_t *ds_len);
620 IGA_API iga_status_t iga_get_errors(
621     iga_context_t ctx,
622     const iga_diagnostic_t **ds,
623     uint32_t *ds_len);
624 
625 
626 /*
627  * Symmetric to 'iga_context_get_errors'.  Various API calls can still succeed
628  * even if there are warnings; hence, robust tools should always check this
629  * as well.
630  */
631 IGA_API iga_status_t iga_context_get_warnings(
632     iga_context_t ctx,
633     const iga_diagnostic_t **ds,
634     uint32_t *ds_len);
635 IGA_API iga_status_t iga_get_warnings(
636     iga_context_t ctx,
637     const iga_diagnostic_t **ds,
638     uint32_t *ds_len);
639 
640 
641 /*
642  * Fetches a diagnostic's message.  The internal memory containing the message
643  * should be copied out before further disassemble or assembly or context
644  * destruction.  This diagnostic field is valid for both binary and text.
645  *
646  * RETURNS:
647  *  IGA_SUCCESS           upon success
648  *  IGA_INVALID_ARG       if an argument is NULL
649  */
650 IGA_API iga_status_t iga_diagnostic_get_message(
651     const iga_diagnostic_t *d,
652     const char **message);
653 
654 
655 /*
656  * Returns the starting file offset for the diagnostic in bytes (zero based).
657  * This diagnostic field is valid for both binary and text.
658  *
659  * RETURNS:
660  *  IGA_SUCCESS           upon success
661  *  IGA_INVALID_ARG       if an argument is NULL or the diagnostic is a binary
662  *                        location
663  */
664 IGA_API iga_status_t iga_diagnostic_get_offset(
665     const iga_diagnostic_t *d,
666     uint32_t *offset);
667 
668 
669 /*
670  * Diagnostics can refer to locations in binary files or text files.
671  * The following enumeration indicates which.
672  */
673 typedef enum {
674     /* the location refers to a text location */
675     IGA_DIAGNOSTIC_TEXT,
676     /* the location refers to a binary location */
677     IGA_DIAGNOSTIC_BINARY,
678 } iga_diagnostic_type_t;
679 
680 
681 /*
682  * Fetches the type of diagnostic (binary or text).
683  * For IGA_DIAGNOSTIC_TEXT iga_diagnostic_text_get_* should be used to access
684  * further information.
685  * For IGA_DIAGNOSTIC_BINARY 'iga_diagnostic_get_offset* should be used
686  * access more the binary offset
687  *
688  * RETURNS:
689  *  IGA_SUCCESS           upon success
690  *  IGA_INVALID_ARG       if an argument is NULL or the diagnostic is a binary
691  *                        location
692  */
693 IGA_API iga_status_t iga_diagnostic_get_type(
694     const iga_diagnostic_t *d,
695     iga_diagnostic_type_t *dt);
696 
697 
698 /*
699  * Fetches a diagnostic's line number (must be IGA_DIAGNOSTIC_TEXT).
700  * Lines numbers are counted from 1.
701  *
702  * RETURNS:
703  *  IGA_SUCCESS           upon success
704  *  IGA_INVALID_ARG       if an argument is NULL or the diagnostic is a binary
705  *                        location
706  */
707 IGA_API iga_status_t iga_diagnostic_get_text_line(
708     const iga_diagnostic_t *d,
709     uint32_t *line);
710 
711 
712 /*
713  * Similar to 'iga_diagnostic_text_get_line', but returns the column.
714  * Columns are counted from 1.
715  */
716 IGA_API iga_status_t iga_diagnostic_get_text_column(
717     const iga_diagnostic_t *d,
718     uint32_t *col);
719 
720 
721 /*
722  * Fetches a binary diagnostic's byte offset (must be IGA_DIAGNOSTIC_TEXT).
723  * The extent is the length of the region of source code.
724  *
725  * RETURNS:
726  *  IGA_SUCCESS           upon success
727  *  IGA_INVALID_ARG       if an argument is NULL or the diagnostic is a binary
728  *                        location
729  */
730 IGA_API iga_status_t iga_diagnostic_get_text_extent(
731     const iga_diagnostic_t *d,
732     uint32_t *extent);
733 
734 
735 
736 /*****************************************************************************/
737 /*             Operation Enumeration Functions                               */
738 /*****************************************************************************/
739 /*
740  * An opaque type representing an operation (instruction) type.
741  * Can be efficiently copied and passed by value.
742  */
743 typedef const struct opspec* iga_opspec_t;
744 
745 /*
746  * Enumerates the opcodes for a given platform.
747  *   'gen'          : gen plaform to enumerate operations on
748  *   'ops_arr'      : a pointer (can be nul) to an array to hold
749  *                    all opcode spec.
750  *   'ops_arr_len'  : the required length for 'ops_arr'
751  * This API is the usual two-shot pattern, in which the caller invokes it
752  * first time to get the length, the caller allocates enough space to hold
753  * info based on the returned length, then the caller invokes it again.
754  *
755  * This function always returns the required length of the array
756  * from argument 'ops_arr_len'.
757  *
758  * For example,
759  *      size_t len;
760  *      iga_opspec_enumerate(gen, nullptr, &len);
761  *      iga_opspec_t *ops_arr =
762  *          (iga_opspec_t*)malloc(sizeof(iga_opspec_t) * len);
763  *      iga_opspec_enumerate(gen, ops_arr, &len);
764  *
765  * RETURNS:
766  *  IGA_SUCCESS           upon success
767  *  IGA_INVALID_ARG       if a gen argument invalid or ops_arr_len is null
768  */
769 IGA_API iga_status_t iga_opspec_enumerate(
770     iga_gen_t gen,
771     iga_opspec_t *ops_arr,
772     size_t *ops_arr_len);
773 
774 
775 /*
776  * Looks up an opspec based on an iga::Op value.
777  *   'gen'          gen plaform
778  *   'op'           the operation value to lookup; this is an iga::Op;
779  *                  an invalid op will succeed but return Op::INVALID
780  *   'os'           the output value
781  *
782  * RETURNS:
783  *  IGA_SUCCESS           upon success
784  *  IGA_INVALID_ARG       if an argument is invalid
785  *                        (invalid GEN or op or null os)
786  */
787 IGA_API iga_status_t iga_opspec_from_op(
788     iga_gen_t gen,
789     /* iga::Op */ uint32_t op_enum,
790     iga_opspec_t *os);
791 
792 
793 /*
794  * Lists the mnemonic name for a given op (e.g. "sends")
795  * (has similar semantics regarding the parameters as 'iga_opspec_enum')
796  *
797  * RETURNS:
798  *  IGA_SUCCESS           upon success
799  *  IGA_INVALID_ARG       if given an invalid argument
800  */
801 IGA_API iga_status_t iga_opspec_mnemonic(
802     const iga_opspec_t op,
803     char *mnemonic,
804     size_t *mnemonic_len);
805 
806 
807 /*
808  * Lists the op name for a given op (e.g. "Split Send Message")
809  * (has similar semantics regarding the parameters as 'iga_opspec_enum')
810  *
811  * RETURNS:
812  *  IGA_SUCCESS           upon success
813  *  IGA_INVALID_ARG       if a gen argument invalid
814  */
815 IGA_API iga_status_t iga_opspec_name(
816     const iga_opspec_t op,
817     char *name,
818     size_t *name_len);
819 
820 
821 /*
822  * Lists the op desription for a given op
823  * (has similar semantics regarding the parameters as 'iga_opspec_enum')
824  *
825  * RETURNS:
826  *  IGA_SUCCESS           upon success
827  *  IGA_INVALID_ARG       if a gen argument invalid
828  */
829 IGA_API iga_status_t iga_opspec_description(
830     iga_opspec_t op,
831     char *desc,
832     size_t *desc_len);
833 
834 
835 /*
836  * Returns iga::Op for this operation as a uint32_t
837  *
838  * RETURNS:
839  *  IGA_SUCCESS           upon success
840  *  IGA_INVALID_ARG       if an argument is NULL
841  */
842 IGA_API iga_status_t iga_opspec_op(
843     iga_opspec_t os,
844     uint32_t *op);
845 
846 
847 /*
848  * Returns iga::Op value opcode encoding.  This can vary for the same op
849  * on platform to platform.
850  *
851  * RETURNS:
852  *  IGA_SUCCESS           upon success
853  *  IGA_INVALID_ARG       if an argument is NULL
854  */
855 IGA_API iga_status_t iga_opspec_op_encoding(
856     iga_opspec_t op,
857     uint32_t *opcode);
858 
859 #ifdef __cplusplus
860 }
861 #endif
862 
863 #endif
864