ae2f_docs
Loading...
Searching...
No Matches
aclspv.c
1/** @file alcpsv.c */
2
3#include <assert.h>
4#include <string.h>
5
6#include <aclspv.h>
7#include <aclspv/abi.h>
8#include <aclspv/spvty.h>
9
10#include <clang-c/CXErrorCode.h>
11#include <clang-c/Index.h>
12
13#include "./impl/asm.h"
14#include "./impl/conf.h"
15
16#include "./util/ctx.h"
17#include "./util/entp.h"
18#include "./util/fn.h"
19#include "./util/iddef.h"
20
21#include "./emit/count_fn.h"
22#include "./emit/decl_glob_obj.h"
23#include "./emit/entp_body.h"
24
25
26/**
27 * @fn aclspv_compile
28 * @brief compile files and generate spir-v for vulkan
29 * @returns <INIT:aclspv_free_obj>
30 * */
31ACLSPV_ABI_DECL e_aclspv_compile_t
32aclspv_compile(
33 struct CXUnsavedFile* ae2f_restrict const rdwr_unsaved,
34 const unsigned c_unsaved_count,
35 const char* ae2f_restrict const * ae2f_restrict const rd_argv_opt,
36 const int c_argc,
37 aclspv_wrdcount_t* ae2f_restrict rwr_output_count_opt,
39 enum CXErrorCode* ae2f_restrict rwr_cxerr_opt
40 )
41{
42 const CXIndex CXIDX = clang_createIndex(0, 0);
43 CXTranslationUnit CXTU = ae2f_NIL;
44 CXCursor CXROOTCUR;
45
46 enum CXErrorCode CXERR = CXError_Success;
47 x_aclspv_ctx CTX;
48
49 unsigned CXTU_IDX_ERR;
50#define STATE_VAL CTX.m_err
51
52 assert(rdwr_unsaved);
53 assert(rwr_output);
54
55 memset(&CTX, 0, sizeof(CTX));
56 init_scale(&CTX.m_scale_vars, 0);
57
58 unless(ae2f_expected(CXIDX)) {
59 CTX.m_err = ACLSPV_COMPILE_MET_INVAL;
60 goto LBL_CLEANUP;
61 }
62
63 CXERR = clang_parseTranslationUnit2(
64 CXIDX, ae2f_NIL
65 , (const char**)rd_argv_opt
66 , c_argc
67 , rdwr_unsaved, c_unsaved_count
68 , CXTranslationUnit_None, &CXTU
69 );
70
71 CXTU_IDX_ERR = clang_getNumDiagnostics(CXTU);
72 while(ae2f_expected(CXTU_IDX_ERR--)) {
73 const CXDiagnostic DIAG = clang_getDiagnostic(CXTU, CXTU_IDX_ERR);
74 enum CXDiagnosticSeverity SEVERITY = clang_getDiagnosticSeverity(DIAG);
75
76 CXString TXT = clang_formatDiagnostic(DIAG, clang_defaultDiagnosticDisplayOptions());
77
78 puts(TXT.data);
79
80 switch(SEVERITY) {
81 case CXDiagnostic_Note:
82 puts("NOTE");
83 break;
84 case CXDiagnostic_Error:
85 puts("_ERR");
86 break;
87 case CXDiagnostic_Warning:
88 puts("WARN");
89 break;
90 case CXDiagnostic_Ignored:
91 puts("IGNR");
92 break;
93 case CXDiagnostic_Fatal:
94 puts("FTAL");
95 break;
96 default:
97 assert(0);
99 }
100
101 clang_disposeString(TXT);
102 }
103
104 if(ae2f_expected_not(CXERR)) {
105 CTX.m_err = ACLSPV_COMPILE_ERR_CLANG;
106 goto LBL_CLEANUP;
107 }
108
109 unless(ae2f_expected(CXTU)) {
110 CTX.m_err = ACLSPV_COMPILE_MET_INVAL;
111 goto LBL_CLEANUP;
112 }
113
114 if(ae2f_expected_not(STATE_VAL = impl_conf(&CTX)))
115 goto LBL_CLEANUP;
116
117 CXROOTCUR = clang_getTranslationUnitCursor(CXTU);
118
119 clang_visitChildren(CXROOTCUR, emit_count_fn, &CTX);
120 if(ae2f_expected_not(STATE_VAL = CTX.m_err))
121 goto LBL_CLEANUP;
122
123 _aclspv_grow_vec(_aclspv_malloc, _aclspv_free, CTX.m_fnlist.m_entp, (size_t)(sizeof(util_entp_t) * CTX.m_fnlist.m_num_entp));
124 _aclspv_grow_vec(_aclspv_malloc, _aclspv_free, CTX.m_fnlist.m_fn, (size_t)(sizeof(lib_build_fn_t) * CTX.m_fnlist.m_num_fn));
125
126 CTX.m_tmp.m_w3 = CTX.m_id; /** anchor */
127 CTX.m_id += CTX.m_fnlist.m_num_entp + CTX.m_fnlist.m_num_fn;
128
129 clang_visitChildren(CXROOTCUR, emit_iter_entry_point, &CTX);
130
131 CTX.m_tmp.m_w0 = 0;
132 clang_visitChildren(CXROOTCUR, emit_decl_glob_obj, &CTX);
133
134 {
135 aclspv_wrdcount_t IDX = CTX.m_fnlist.m_num_entp;
136 const aclspv_wrd_t ANCHOR = CTX.m_tmp.m_w3;
137
138 util_get_default_id(ID_DEFAULT_VOID, &CTX);
139 util_get_default_id(ID_DEFAULT_FN_VOID, &CTX);
140
141
142 while((IDX--)) {
143 ((util_entp_t* ae2f_restrict)CTX.m_fnlist.m_entp.m_p)[IDX].m_id = ANCHOR + IDX;
144 }
145
146 IDX = CTX.m_fnlist.m_num_entp;
147 while((IDX--)) {
148 /**
149 * IDX must be w0 at the end
150 * w0: current entry point index
151 * v0: current variable table (scale)
152 * */
153#define FNINFO ((util_entp_t* ae2f_restrict)CTX.m_fnlist.m_entp.m_p)[CTX.m_tmp.m_w0]
154 x_scale* ae2f_restrict const FNSCALE = get_scale_from_vec(&CTX.m_scale_vars
155 , (size_t)(CTX.m_tmp.m_w0 = IDX)
156 );
157
158 CTX.m_count.m_fnimpl = 0;
159
160 ae2f_expected_but_else(CTX.m_scale_vars.m_p && FNSCALE) {
161 CTX.m_err = ACLSPV_COMPILE_MET_INVAL;
162 goto LBL_CLEANUP;
163 }
164
165
166 CTX.m_err = ACLSPV_COMPILE_ALLOC_FAILED;
167 CTX.m_tmp.m_w0 = IDX;
168
169
170 ae2f_expected_but_else(CTX.m_count.m_fndef = util_emitx_5(
171 &CTX.m_section.m_fndef
172 , CTX.m_count.m_fndef
173 , SpvOpFunction
174 , ID_DEFAULT_VOID
175 , FNINFO.m_id
176 , 0
177 , ID_DEFAULT_FN_VOID
178 )) goto LBL_CLEANUP;
179
180 ae2f_expected_but_else(CTX.m_count.m_fndef = util_emitx_2(
181 &CTX.m_section.m_fndef
182 , CTX.m_count.m_fndef
183 , SpvOpLabel
184 , CTX.m_id++))
185 goto LBL_CLEANUP;
186
187 IDX = (aclspv_wrd_t)FNSCALE->m_sz / (size_t)sizeof(util_bind);
188 CTX.m_num_cursor = IDX;
189
190 while(IDX--) {
191 const util_bind* ae2f_restrict const BUFFER = get_buf_from_scale(&CTX.m_scale_vars, FNSCALE[0]);
192 const aclspv_wrd_t CURSOR_IDX = util_mk_cursor_base(
194 , &CTX.m_cursors
195 , BUFFER[IDX].m_unified.m_cursor
196 );
197
198 assert(CTX.m_scale_vars.m_p);
199 assert(BUFFER);
200
201 ae2f_unexpected_but_if(CURSOR_IDX == CTX.m_num_cursor + 1)
202 goto LBL_CLEANUP;
203
204 if(CURSOR_IDX == CTX.m_num_cursor)
205 ++CTX.m_num_cursor;
206
207 CURSOR_IDX[(util_cursor* ae2f_restrict)CTX.m_cursors.m_p]
208 .m_data.m_prm_decl.m_info = BUFFER[IDX];
209 }
210 IDX = CTX.m_tmp.m_w0;
211
212
213#undef FNINFO
214
215 CTX.m_has_function_ret = 0;
216 clang_visitChildren(((util_entp_t* ae2f_restrict)CTX.m_fnlist.m_entp.m_p)[IDX].m_fn
217 , emit_entp_body
218 , &CTX);
219 ae2f_unexpected_but_if(STATE_VAL) goto LBL_CLEANUP;
220
221 if(CTX.m_count.m_fnimpl) {
222 _aclspv_grow_vec_with_copy(_aclspv_malloc, _aclspv_free, _aclspv_memcpy, L_new
223 , CTX.m_section.m_fndef
224 , (size_t)count_to_sz(CTX.m_count.m_fndef + CTX.m_count.m_fnimpl)
225 );
226
227 ae2f_expected_but_else(CTX.m_section.m_fndef.m_p) {
228 CTX.m_err = ACLSPV_COMPILE_ALLOC_FAILED;
229 goto LBL_CLEANUP;
230 }
231
232 memcpy(
233 get_wrd_of_vec(&CTX.m_section.m_fndef) + CTX.m_count.m_fndef
234 , CTX.m_section.m_fnimpl.m_p
235 , (size_t)count_to_sz(CTX.m_count.m_fnimpl)
236 );
237
238 CTX.m_count.m_fndef += CTX.m_count.m_fnimpl;
239 }
240
241 unless(CTX.m_has_function_ret) {
242 ae2f_expected_but_else(CTX.m_count.m_fndef = emit_opcode(
243 &CTX.m_section.m_fndef
244 , CTX.m_count.m_fndef
245 , SpvOpReturn, 0
246 )) {
247 CTX.m_err = ACLSPV_COMPILE_ALLOC_FAILED;
248 goto LBL_CLEANUP;
249 }
250 }
251
252 ae2f_expected_but_else(CTX.m_count.m_fndef = emit_opcode(
253 &CTX.m_section.m_fndef
254 , CTX.m_count.m_fndef
255 , SpvOpFunctionEnd, 0
256 )) {
257 CTX.m_err = ACLSPV_COMPILE_ALLOC_FAILED;
258 goto LBL_CLEANUP;
259 }
260
261 assert(IDX == CTX.m_tmp.m_w0);
262 { ae2f_assume(IDX == CTX.m_tmp.m_w0); }
263 }
264 }
265
266
267 if(ae2f_expected_not(STATE_VAL = CTX.m_err))
268 goto LBL_CLEANUP;
269
270
271 if(ae2f_expected_not(STATE_VAL = impl_asm(&CTX)))
272 goto LBL_CLEANUP;
273
274LBL_CLEANUP:
275 clang_disposeTranslationUnit(CXTU);
276 _aclspv_stop_vec(_aclspv_free, CTX.m_constant_cache);
277 _aclspv_stop_vec(_aclspv_free, CTX.m_type_uniques);
278 _aclspv_stop_vec(_aclspv_free, CTX.m_cursors);
279 _aclspv_stop_vec(_aclspv_free, CTX.m_scale_vars);
280
281 _aclspv_stop_vec(_aclspv_free, CTX.m_fnlist.m_entp);
282 _aclspv_stop_vec(_aclspv_free, CTX.m_fnlist.m_fn);
283
284 _aclspv_stop_vec(_aclspv_free, CTX.m_tmp.m_v0);
285 _aclspv_stop_vec(_aclspv_free, CTX.m_tmp.m_v1);
286
287 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_capability);
288 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_decorate);
289 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_entp);
290 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_fndef);
291 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_execmode);
292 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_ext);
293 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_memmodel);
294 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_name);
295 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_types);
296 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_vars);
297 _aclspv_stop_vec(_aclspv_free, CTX.m_section.m_fnimpl);
298
299
300 if(ae2f_expected(CXIDX)) clang_disposeIndex(CXIDX);
301 if(ae2f_expected(rwr_cxerr_opt)) *rwr_cxerr_opt = CXERR;
302 if((rwr_output)) *rwr_output = CTX.m_ret.m_p;
303 else free(CTX.m_ret.m_p);
304
305 if(ae2f_expected(rwr_output_count_opt)) *rwr_output_count_opt = CTX.m_num_ret;
306
307 return CTX.m_err;
308}
#define unless(a)
Invokes when condition is false.
Definition Keys.h:34
#define ae2f_NIL
Definition Nil.h:13
#define ACLSPV_ABI_DECL
Declaration as ABI.
Definition abi.h:23
#define STATE_VAL
#define FNINFO
#define ae2f_assume(a)
tells the compiler that value if a is false, below this keyword is not expected to be reached.
Definition cc.h:228
#define ae2f_unexpected_but_if(a)
Definition cc.h:192
#define ae2f_expected_but_else(a)
Definition cc.h:201
#define ae2f_restrict
Keyword as restrict on C99.
Definition cc.h:81
#define ae2f_expected_not(a)
expectes a as false.
Definition cc.h:185
#define ae2f_unreachable()
tells the compiler that below this keyword is not expected to be reached.
Definition cc.h:213
#define ae2f_expected(a)
expectes a as true.
Definition cc.h:184
#define get_buf_from_scale(h_alloc, c_scale)
Definition scale.h:34
aclspv_wrd_t aclspv_wrdcount_t
the integer type represents the number of word.
Definition spvty.h:61
#define aclspv_wrd_t
integer as word
Definition spvty.h:16
aclspv_id_t m_id
id
Definition ctx.h:50
aclspv_wrdcount_t m_num_cursor
number of m_cursors. for its use see util/cursor.h
Definition ctx.h:41
util_bind_unified m_unified
Definition bind.h:20
#define emit_opcode(h_wrds, c_wrdcount, c_opcode, c_num_opprm_opt)
try emit opcode with num_opprm
Definition wrdemit.h:75
#define get_wrd_of_vec(vec)
get word buffer from vector
Definition wrdemit.h:38
#define count_to_sz(c_count)
word count to byte size
Definition wrdemit.h:32