3#include "aclspv/spvty.h"
10#include <util/emitx.h>
11#include <util/is_kernel.h>
15#include <util/constant.h>
16#include <util/scale.h>
18#include <attr/specid.h>
19#include <attr/location.h>
20#include <attr/storage_class.h>
23#include <ae2f/c90/StdBool.h>
24#include <ae2f/c90/StdInt.h>
26#include <spirv/unified1/spirv.h>
27#include <clang-c/Index.h>
29static enum CXChildVisitResult emit_decl_glob_obj_visit_attr_set(CXCursor h_cur, CXCursor h_parent, CXClientData
ae2f_restrict h_data) {
31 enum CXChildVisitResult RES = CXChildVisit_Break;
35 unless(h_cur.kind == CXCursor_AnnotateAttr)
return CXChildVisit_Recurse;
36 TEXT = clang_getCursorSpelling(h_cur);
38 unless(NEEDLE = strstr(TEXT.data,
"aclspv_set")) {
39 RES = CXChildVisit_Continue;
44 sscanf(NEEDLE,
"aclspv_set ( %u )", &SET);
49 clang_disposeString(TEXT);
55static enum CXChildVisitResult emit_decl_glob_obj_visit_fetch(CXCursor h_cur, CXCursor h_parent, CXClientData h_data) {
56#if !defined(NDEBUG) || !NDEBUG
58 CXString PARAM_NAME, FUNC_NAME;
61 CXString PARAM_TY_NAME;
66#define CTX ((h_aclspv_ctx_t)((uintptr_t* ae2f_restrict)h_data)[2
])
73#define INFO (((INTERFACES + ARG_IDX)))
75 unless(h_cur.kind == CXCursor_ParmDecl) {
76 return CXChildVisit_Continue;
79 PARAM_TY = clang_getCursorType(h_cur);
81 CTX->m_err = ACLSPV_COMPILE_TOO_BIG;
82 return CXChildVisit_Break;
90 grow_last_scale(&
CTX->m_scale_vars, (size_t)(
sizeof(util_bind) * (
ARG_IDX + 1)))
92 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
93 return CXChildVisit_Break;
101 unless(PARAM_TY.kind == CXType_Pointer || PARAM_TY.kind == CXType_ConstantArray) {
111 return CXChildVisit_Continue;
122#if !defined(NDEBUG) || !NDEBUG
123 FUNC_NAME = clang_getCursorSpelling(h_parent);
124 PARAM_NAME = clang_getCursorSpelling(h_cur);
128 NAME_MERGE = malloc(strlen(FUNC_NAME.data) + strlen(PARAM_NAME.data) + 3);
132 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
134 clang_disposeString(FUNC_NAME);
135 clang_disposeString(PARAM_NAME);
136 return CXChildVisit_Break;
139 strcpy(NAME_MERGE, FUNC_NAME.data);
140 strcat(NAME_MERGE,
"::");
141 strcat(NAME_MERGE, PARAM_NAME.data);
143#define EMIT_POS CTX->m_count.m_name
145 goto LBL_ABRT_NALLOC;
147 goto LBL_ABRT_NALLOC;
149 goto LBL_ABRT_NALLOC;
158#if !defined(NDEBUG) || !NDEBUG
159 clang_disposeString(FUNC_NAME);
160 clang_disposeString(PARAM_NAME);
165 PARAM_TY_NAME = clang_getTypeSpelling(PARAM_TY);
167 if(PARAM_TY.kind == CXType_ConstantArray)
169 else if(strstr(PARAM_TY_NAME.data,
"global")) {
171 }
else if (strstr(PARAM_TY_NAME.data,
"constant")) {
182 clang_disposeString(PARAM_TY_NAME);
186 case SpvStorageClassMax:
187 CTX->m_err = ACLSPV_COMPILE_STORAGE_CLASS_UNDEFINED;
188 return CXChildVisit_Break;
193 case SpvStorageClassUniform:
196 return CXChildVisit_Break;
200 case SpvStorageClassStorageBuffer:
201 clang_visitChildren(h_cur
202 , emit_decl_glob_obj_visit_attr_set
206 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
210 &
CTX->m_section.m_decorate
211 ,
CTX->m_count.m_decorate
214 , SpvDecorationDescriptorSet
216 ))
return CXChildVisit_Break;
220 &
CTX->m_section.m_decorate
221 ,
CTX->m_count.m_decorate
224 , SpvDecorationBinding
225 ,
INFO->m_bindable.m_binding
226 ))
return CXChildVisit_Break;
229 &
CTX->m_section.m_vars
230 ,
CTX->m_count.m_vars
234 ))
return CXChildVisit_Break;
239 case SpvStorageClassWorkgroup:
240 PARAM_TY_NAME = clang_getTypeSpelling(PARAM_TY);
241 unless(strstr(PARAM_TY_NAME.data,
"local")) {
242 clang_disposeString(PARAM_TY_NAME);
243 CTX->m_err = ACLSPV_COMPILE_MET_INVAL;
244 return CXChildVisit_Break;
245 } clang_disposeString(PARAM_TY_NAME);
247 unless(PARAM_TY.kind == CXType_ConstantArray) {
248 CTX->m_err = ACLSPV_COMPILE_WORKGROUP_MUST_BE_CONSTANT_ARRAY;
249 return CXChildVisit_Break;
254 const intmax_t NUM_ARR_ORIG = clang_getArraySize(PARAM_TY);
255 const intmax_t REAL_ARR_ORIG = clang_Type_getSizeOf(PARAM_TY);
259 const aclspv_id_t VAL_ELM = util_mk_constant_val_id(ELM_ARR,
CTX);
260 const aclspv_id_t VAL_2 = util_mk_constant_val_id(2,
CTX);
262 const aclspv_id_t VAL_3 = util_mk_constant_val_id(3,
CTX);
264 assert(REAL_ARR >= NUM_ARR && !(REAL_ARR % NUM_ARR));
265 {
ae2f_assume(REAL_ARR >= NUM_ARR && !(REAL_ARR % NUM_ARR)); }
277 CTX->m_err = ACLSPV_COMPILE_MET_INVAL;
278 return CXChildVisit_Break;
282 util_constant* CONST_NODE = util_mk_constant_node(SPECID_WORK,
CTX);
284 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
287 return CXChildVisit_Break;
291 return CXChildVisit_Break;
293 unless(CONST_NODE->m_const_spec_id) {
295 &
CTX->m_section.m_types
296 ,
CTX->m_count.m_types
303 RETCOUNT_TY ? util_emitx_4(&
CTX->m_section.m_decorate
304 ,
CTX->m_count.m_decorate
307 , SpvDecorationSpecId
313 return CXChildVisit_Break;
316 CONST_NODE->m_const_spec_id =
CTX->m_id++;
317 CONST_NODE->m_const_spec_type_id = ID_DEFAULT_U32;
318 CTX->m_count.m_types = RETCOUNT_TY;
319 CTX->m_count.m_decorate = RETCOUNT_DC;
321 CTX->m_err = ACLSPV_COMPILE_MET_INVAL;
322 return CXChildVisit_Break;
332 &
CTX->m_section.m_types
333 ,
CTX->m_count.m_types
340 return CXChildVisit_Break;
343 &
CTX->m_section.m_types
344 ,
CTX->m_count.m_types
351 return CXChildVisit_Break;
354 &
CTX->m_section.m_types
355 ,
CTX->m_count.m_types
358 , SpvOpShiftRightLogical
361 ))
return CXChildVisit_Break;
364 &
CTX->m_section.m_types
365 ,
CTX->m_count.m_types
369 ))
return CXChildVisit_Break;
372 &
CTX->m_section.m_types
373 ,
CTX->m_count.m_types
375 , SpvStorageClassWorkgroup
377 ))
return CXChildVisit_Break;
385 CTX->m_err = ACLSPV_COMPILE_OK;
391 &
CTX->m_section.m_vars
392 ,
CTX->m_count.m_vars
395 , SpvStorageClassWorkgroup
396 ))
return CXChildVisit_Break;
405 case SpvStorageClassInput:
411 case SpvStorageClassOutput:
415 clang_visitChildren(h_cur, attr_location, &
INFO->m_io.m_location);
416#define THIS_ENTP ((util_entp_t* ae2f_restrict)CTX->m_fnlist.m_entp.m_p)[CTX->m_tmp.m_w0]
423 &
CTX->m_section.m_decorate
424 ,
CTX->m_count.m_decorate
427 , SpvDecorationLocation
428 ,
INFO->m_io.m_location
429 ))
return CXChildVisit_Break;
432 &
CTX->m_section.m_vars
433 ,
CTX->m_count.m_vars
437 ))
return CXChildVisit_Break;
446 CTX->m_err = ACLSPV_COMPILE_OK;
449 return CXChildVisit_Continue;
456#undef INTERFACE_COUNT
466static enum CXChildVisitResult emit_decl_glob_obj(CXCursor h_cur, CXCursor h_cur_parent, CXClientData h_ctx) {
470 unless(h_cur.kind == CXCursor_CompoundStmt && h_cur_parent.kind == CXCursor_FunctionDecl)
471 return CXChildVisit_Recurse;
473 if(util_is_kernel(h_cur_parent)) {
474 uintptr_t BUFF[7] = {
484 const int NPARAMS = clang_Cursor_getNumArguments(h_cur_parent);
486 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
489 CTX->m_err = ACLSPV_COMPILE_MET_INVAL;
490 return CXChildVisit_Break;
493 unless(NPARAMS)
goto LBL_HOLLOW_ENTP;
495 BUFF[2] = (uintptr_t)
CTX;
497 _aclspv_grow_vec(_aclspv_malloc, _aclspv_free,
CTX->m_tmp.m_v0, (size_t)((
unsigned)NPARAMS *
sizeof(CXType)));
499 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
500 return CXChildVisit_Break;
503 clang_visitChildren(h_cur_parent, emit_decl_glob_obj_visit_fetch, BUFF);
506 CTX->m_err = ACLSPV_COMPILE_TOO_BIG;
507 return CXChildVisit_Break;
511 if(
CTX->m_tmp.m_w2 < BUFF[0]) {
516 const aclspv_id_t PSH_PTR_ID = util_mk_constant_ptr_psh_id((
aclspv_wrd_t)BUFF[0],
CTX);
519#if !defined(NDEBUG) || !NDEBUG
521 CXString NAME_STR = clang_getCursorSpelling(h_cur_parent);
522 char*
ae2f_restrict NAME = NAME_STR.data ? malloc(strlen(NAME_STR.data) + (size_t)
sizeof(
":::push")) : 0;
526 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
527 goto LBL_DBG_STR_DISPOSE_FAIL;
530 CTX->m_err = ACLSPV_COMPILE_ALLOC_FAILED;
533 &
CTX->m_section.m_vars
534 ,
CTX->m_count.m_vars
538 , SpvStorageClassPushConstant
539 ))
goto LBL_DBG_STR_DISPOSE_FAIL;
542#if !defined(NDEBUG) || !NDEBUG
543#define EMIT_POS CTX->m_count.m_name
545 strcpy(NAME, NAME_STR.data);
546 strcat(NAME,
":::push");
550 goto LBL_DBG_STR_DISPOSE_FAIL;
552 goto LBL_DBG_STR_DISPOSE_FAIL;
554 goto LBL_DBG_STR_DISPOSE_FAIL;
556 clang_disposeString(NAME_STR);
561LBL_DBG_STR_DISPOSE_FAIL:
562 clang_disposeString(NAME_STR);
564 return CXChildVisit_Break;
570 CTX->m_err = ACLSPV_COMPILE_OK;
572 ((util_entp_t*
ae2f_restrict)
CTX->m_fnlist.m_entp.m_p)[
CTX->m_tmp.m_w0].m_push_ids.m_push_ptr
574 ((util_entp_t*
ae2f_restrict)
CTX->m_fnlist.m_entp.m_p)[
CTX->m_tmp.m_w0].m_push_ids.m_push_var
576 ((util_entp_t*
ae2f_restrict)
CTX->m_fnlist.m_entp.m_p)[
CTX->m_tmp.m_w0].m_push_ids.m_push_struct
585 mk_scale_from_vec(&
CTX->m_scale_vars, 0);
590 return CXChildVisit_Continue;
595#if !defined(NDEBUG) || !NDEBUG
597LBL_DBG_STR_DISPOSE_FAIL:
598 return CXChildVisit_Break;
#define ae2f_WhenCXX(a)
Appears when the current language is C.
#define ae2f_WhenC(a)
Appears when the current language is C++.
#define unless(a)
Invokes when condition is false.
#define ae2f_extern
Suggests the existence of external variable or function, in naming of C. [non-mangling].
#define ACLSPV_ABI_DECL
Declaration as ABI.
#define ae2f_assume(a)
tells the compiler that value if a is false, below this keyword is not expected to be reached.
#define ae2f_unexpected_but_if(a)
#define ae2f_ccpure
Keyword as [[pure]] on C23.
#define ae2f_expected_but_else(a)
#define ae2f_expected_if(a)
#define ae2f_ccconst
Keyword as [[const]] on C23..
#define ae2f_noexcept
marker that this function does not throw something.
#define ae2f_restrict
Keyword as restrict on C99.
#define ae2f_expected_not(a)
expectes a as false.
#define ae2f_unreachable()
tells the compiler that below this keyword is not expected to be reached.
#define ae2f_fallthrough
explicitly tells compiler that fallthrough on switch is expected.
#define ae2f_inline
inline
#define ae2f_expected(a)
expectes a as true.
#define util_emitx_spec_constant(h_wrds, c_wrdcount, c_ty, c_retid, c_val)
#define util_emitx_variable(h_wrds, c_wrdcount, c_type, c_retid, c_storage_class)
#define util_emitx_spec_constant_op2(h_wrds, c_wrdcount, c_retid, c_ty, c_operator, c_opr_0, c_opr_1)
#define util_emitx_type_array(h_wrds, c_wrdcount, c_retid, c_elm_type_id, c_arrcount_id)
#define util_emitx_type_pointer(h_wrds, c_wrdcount, c_retid, c_storage_class, c_elm_type_id)
#define get_buf_from_scale(h_alloc, c_scale)
#define get_last_scale_from_vec(h_alloc)
#define aclspv_opcode_t
integer as operation code
aclspv_wrd_t aclspv_wrdcount_t
the integer type represents the number of word.
#define ACLSPV_MASK_OPCODE
mask for opcode
#define aclspv_wrd_t
integer as word
#define ACLSPV_MASK_NOPRNDS
mask for number of operands
x_aclspv_vec m_scale_vars
aclspv_wrdcount_t m_num_type_uniques
x_aclspv_vec m_cursors
cache for cursors for parsing one function for its use see util/cursor.h
x_aclspv_vec m_constant_cache
x_aclspv_vec m_ret
word count for m_ret
aclspv_wrd_t m_is_logical
when on, ignores m_is_buffer_64.
aclspv_wrdcount_t m_num_cursor
number of m_cursors. for its use see util/cursor.h
x_aclspv_vec m_type_uniques
cache for complex types which needs to be stored somewhere for its use see util/type_unique....
aclspv_wrdcount_t m_arr_count_id
util_bind_unified m_unified
#define mk_noprnds(c_num_opprm)
#define emit_opcode(h_wrds, c_wrdcount, c_opcode, c_num_opprm_opt)
try emit opcode with num_opprm
#define sz_to_count(c_sz)
byte size to word count
#define get_wrd_of_vec(vec)
get word buffer from vector
aclspv_wrdcount_t spvsz_t
#define count_to_sz(c_count)
word count to byte size
#define set_oprnd_count_for_opcode(cr_wrd, c_num_opprm)
#define opcode_to_wrd(c_opcode, c_num_opprm)