4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright (c) 2013 by Delphix. All rights reserved.
28 * Copyright (c) 2013 Joyent, Inc. All rights reserved.
34 #include <dt_xlator.h>
35 #include <dt_parser.h>
36 #include <dt_grammar.h>
37 #include <dt_module.h>
41 * Create a member node corresponding to one of the output members of a dynamic
42 * translator. We set the member's dn_membexpr to a DT_NODE_XLATOR node that
43 * has dn_op set to DT_TOK_XLATE and refers back to the translator itself. The
44 * code generator will then use this as the indicator for dynamic translation.
48 dt_xlator_create_member(const char *name
, ctf_id_t type
, ulong_t off
, void *arg
)
50 dt_xlator_t
*dxp
= arg
;
51 dtrace_hdl_t
*dtp
= dxp
->dx_hdl
;
55 if ((enp
= dt_node_xalloc(dtp
, DT_NODE_XLATOR
)) == NULL
)
56 return (dt_set_errno(dtp
, EDT_NOMEM
));
58 enp
->dn_link
= dxp
->dx_nodes
;
61 if ((mnp
= dt_node_xalloc(dtp
, DT_NODE_MEMBER
)) == NULL
)
62 return (dt_set_errno(dtp
, EDT_NOMEM
));
64 mnp
->dn_link
= dxp
->dx_nodes
;
68 * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose
69 * xlator refers back to the translator and whose dn_xmember refers to
70 * the current member. These refs will be used by dt_cg.c and dt_as.c.
72 enp
->dn_op
= DT_TOK_XLATE
;
74 enp
->dn_xmember
= mnp
;
76 * XXX: Is it ok for the CTF of the type to not be from the dst ctf?
78 * I suspect it's actually unnecessary, but I'm also unclear on
81 dt_resolve_forward_decl(&ctfp
, &type
);
82 dt_node_type_assign(enp
, ctfp
, type
, B_FALSE
);
85 * For the member itself, we use a DT_NODE_MEMBER as usual with the
86 * appropriate name, output type, and member expression set to 'enp'.
88 if (dxp
->dx_members
!= NULL
) {
89 assert(enp
->dn_link
->dn_kind
== DT_NODE_MEMBER
);
90 enp
->dn_link
->dn_list
= mnp
;
92 dxp
->dx_members
= mnp
;
94 mnp
->dn_membname
= strdup(name
);
95 mnp
->dn_membexpr
= enp
;
96 dt_node_type_assign(mnp
, dxp
->dx_dst_ctfp
, type
, B_FALSE
);
98 if (mnp
->dn_membname
== NULL
)
99 return (dt_set_errno(dtp
, EDT_NOMEM
));
105 dt_xlator_create(dtrace_hdl_t
*dtp
,
106 const dtrace_typeinfo_t
*src
, const dtrace_typeinfo_t
*dst
,
107 const char *name
, dt_node_t
*members
, dt_node_t
*nodes
)
109 dt_xlator_t
*dxp
= dt_zalloc(dtp
, sizeof (dt_xlator_t
));
110 dtrace_typeinfo_t ptr
= *dst
;
119 dxp
->dx_id
= dtp
->dt_xlatorid
++;
120 dxp
->dx_gen
= dtp
->dt_gen
;
123 if ((map
= dt_alloc(dtp
, sizeof (void *) * (dxp
->dx_id
+ 1))) == NULL
) {
128 dt_list_append(&dtp
->dt_xlators
, dxp
);
129 bcopy(dtp
->dt_xlatormap
, map
, sizeof (void *) * dxp
->dx_id
);
130 dt_free(dtp
, dtp
->dt_xlatormap
);
131 dtp
->dt_xlatormap
= map
;
132 dtp
->dt_xlatormap
[dxp
->dx_id
] = dxp
;
134 if (dt_type_pointer(&ptr
) == -1) {
136 ptr
.dtt_type
= CTF_ERR
;
139 dxp
->dx_ident
= dt_ident_create(name
? name
: "T",
140 DT_IDENT_SCALAR
, DT_IDFLG_REF
| DT_IDFLG_ORPHAN
, 0,
141 _dtrace_defattr
, 0, &dt_idops_thaw
, NULL
, dtp
->dt_gen
);
143 if (dxp
->dx_ident
== NULL
)
144 goto err
; /* no memory for identifier */
146 dxp
->dx_ident
->di_ctfp
= src
->dtt_ctfp
;
147 dxp
->dx_ident
->di_type
= src
->dtt_type
;
150 * If an input parameter name is given, this is a static translator
151 * definition: create an idhash and identifier for the parameter.
154 dxp
->dx_locals
= dt_idhash_create("xlparams", NULL
, 0, 0);
156 if (dxp
->dx_locals
== NULL
)
157 goto err
; /* no memory for identifier hash */
159 dt_idhash_xinsert(dxp
->dx_locals
, dxp
->dx_ident
);
162 dxp
->dx_souid
.di_name
= "translator";
163 dxp
->dx_souid
.di_kind
= DT_IDENT_XLSOU
;
164 dxp
->dx_souid
.di_flags
= DT_IDFLG_REF
;
165 dxp
->dx_souid
.di_id
= dxp
->dx_id
;
166 dxp
->dx_souid
.di_attr
= _dtrace_defattr
;
167 dxp
->dx_souid
.di_ops
= &dt_idops_thaw
;
168 dxp
->dx_souid
.di_data
= dxp
;
169 dxp
->dx_souid
.di_ctfp
= dst
->dtt_ctfp
;
170 dxp
->dx_souid
.di_type
= dst
->dtt_type
;
171 dxp
->dx_souid
.di_gen
= dtp
->dt_gen
;
173 dxp
->dx_ptrid
.di_name
= "translator";
174 dxp
->dx_ptrid
.di_kind
= DT_IDENT_XLPTR
;
175 dxp
->dx_ptrid
.di_flags
= DT_IDFLG_REF
;
176 dxp
->dx_ptrid
.di_id
= dxp
->dx_id
;
177 dxp
->dx_ptrid
.di_attr
= _dtrace_defattr
;
178 dxp
->dx_ptrid
.di_ops
= &dt_idops_thaw
;
179 dxp
->dx_ptrid
.di_data
= dxp
;
180 dxp
->dx_ptrid
.di_ctfp
= ptr
.dtt_ctfp
;
181 dxp
->dx_ptrid
.di_type
= ptr
.dtt_type
;
182 dxp
->dx_ptrid
.di_gen
= dtp
->dt_gen
;
185 * If a deferred pragma is pending on the keyword "translator", run all
186 * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
187 * See the code in dt_pragma.c for details on deferred ident pragmas.
189 if (dtp
->dt_globals
->dh_defer
!= NULL
&& yypcb
->pcb_pragmas
!= NULL
&&
190 dt_idhash_lookup(yypcb
->pcb_pragmas
, "translator") != NULL
) {
191 dtp
->dt_globals
->dh_defer(dtp
->dt_globals
, &dxp
->dx_souid
);
192 dxp
->dx_ptrid
.di_attr
= dxp
->dx_souid
.di_attr
;
193 dxp
->dx_ptrid
.di_vers
= dxp
->dx_souid
.di_vers
;
196 dxp
->dx_src_ctfp
= src
->dtt_ctfp
;
197 dxp
->dx_src_type
= src
->dtt_type
;
198 dxp
->dx_src_base
= ctf_type_resolve(src
->dtt_ctfp
, src
->dtt_type
);
200 dxp
->dx_dst_ctfp
= dst
->dtt_ctfp
;
201 dxp
->dx_dst_type
= dst
->dtt_type
;
202 dxp
->dx_dst_base
= ctf_type_resolve(dst
->dtt_ctfp
, dst
->dtt_type
);
204 kind
= ctf_type_kind(dst
->dtt_ctfp
, dxp
->dx_dst_base
);
205 assert(kind
== CTF_K_STRUCT
|| kind
== CTF_K_UNION
);
208 * If no input parameter is given, we're making a dynamic translator:
209 * create member nodes for every member of the output type. Otherwise
210 * retain the member and allocation node lists presented by the parser.
213 if (ctf_member_iter(dxp
->dx_dst_ctfp
, dxp
->dx_dst_base
,
214 dt_xlator_create_member
, dxp
) != 0)
217 dxp
->dx_members
= members
;
218 dxp
->dx_nodes
= nodes
;
222 * Assign member IDs to each member and allocate space for DIFOs
223 * if and when this translator is eventually compiled.
225 for (dnp
= dxp
->dx_members
; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
226 dnp
->dn_membxlator
= dxp
;
227 dnp
->dn_membid
= dxp
->dx_nmembers
++;
230 dxp
->dx_membdif
= dt_zalloc(dtp
,
231 sizeof (dtrace_difo_t
*) * dxp
->dx_nmembers
);
233 if (dxp
->dx_membdif
== NULL
) {
234 dxp
->dx_nmembers
= 0;
241 dt_xlator_destroy(dtp
, dxp
);
246 dt_xlator_destroy(dtrace_hdl_t
*dtp
, dt_xlator_t
*dxp
)
250 dt_node_link_free(&dxp
->dx_nodes
);
252 if (dxp
->dx_locals
!= NULL
)
253 dt_idhash_destroy(dxp
->dx_locals
);
254 else if (dxp
->dx_ident
!= NULL
)
255 dt_ident_destroy(dxp
->dx_ident
);
257 for (i
= 0; i
< dxp
->dx_nmembers
; i
++)
258 dt_difo_free(dtp
, dxp
->dx_membdif
[i
]);
260 dt_free(dtp
, dxp
->dx_membdif
);
261 dt_list_delete(&dtp
->dt_xlators
, dxp
);
266 dt_xlator_lookup(dtrace_hdl_t
*dtp
, dt_node_t
*src
, dt_node_t
*dst
, int flags
)
268 ctf_file_t
*src_ctfp
= src
->dn_ctfp
;
269 ctf_id_t src_type
= src
->dn_type
;
270 ctf_id_t src_base
= ctf_type_resolve(src_ctfp
, src_type
);
272 ctf_file_t
*dst_ctfp
= dst
->dn_ctfp
;
273 ctf_id_t dst_type
= dst
->dn_type
;
274 ctf_id_t dst_base
= ctf_type_resolve(dst_ctfp
, dst_type
);
275 uint_t dst_kind
= ctf_type_kind(dst_ctfp
, dst_base
);
277 int ptr
= dst_kind
== CTF_K_POINTER
;
278 dtrace_typeinfo_t src_dtt
, dst_dtt
;
279 dt_node_t xn
= { 0 };
280 dt_xlator_t
*dxp
= NULL
;
282 if (src_base
== CTF_ERR
|| dst_base
== CTF_ERR
)
283 return (NULL
); /* fail if these are unresolvable types */
286 * Translators are always defined using a struct or union type, so if
287 * we are attempting to translate to type "T *", we internally look
288 * for a translation to type "T" by following the pointer reference.
291 dst_type
= ctf_type_reference(dst_ctfp
, dst_type
);
292 dst_base
= ctf_type_resolve(dst_ctfp
, dst_type
);
293 dst_kind
= ctf_type_kind(dst_ctfp
, dst_base
);
296 if (dst_kind
!= CTF_K_UNION
&& dst_kind
!= CTF_K_STRUCT
)
297 return (NULL
); /* fail if the output isn't a struct or union */
300 * In order to find a matching translator, we iterate over the set of
301 * available translators in three passes. First, we look for a
302 * translation from the exact source type to the resolved destination.
303 * Second, we look for a translation from the resolved source type to
304 * the resolved destination. Third, we look for a translation from a
305 * compatible source type (using the same rules as parameter formals)
306 * to the resolved destination. If all passes fail, return NULL.
308 for (dxp
= dt_list_next(&dtp
->dt_xlators
); dxp
!= NULL
;
309 dxp
= dt_list_next(dxp
)) {
310 if (ctf_type_compat(dxp
->dx_src_ctfp
, dxp
->dx_src_type
,
311 src_ctfp
, src_type
) &&
312 ctf_type_compat(dxp
->dx_dst_ctfp
, dxp
->dx_dst_base
,
317 if (flags
& DT_XLATE_EXACT
)
318 goto out
; /* skip remaining passes if exact match required */
320 for (dxp
= dt_list_next(&dtp
->dt_xlators
); dxp
!= NULL
;
321 dxp
= dt_list_next(dxp
)) {
322 if (ctf_type_compat(dxp
->dx_src_ctfp
, dxp
->dx_src_base
,
323 src_ctfp
, src_type
) &&
324 ctf_type_compat(dxp
->dx_dst_ctfp
, dxp
->dx_dst_base
,
329 for (dxp
= dt_list_next(&dtp
->dt_xlators
); dxp
!= NULL
;
330 dxp
= dt_list_next(dxp
)) {
331 dt_node_type_assign(&xn
, dxp
->dx_src_ctfp
, dxp
->dx_src_type
,
333 if (ctf_type_compat(dxp
->dx_dst_ctfp
, dxp
->dx_dst_base
,
334 dst_ctfp
, dst_base
) && dt_node_is_argcompat(src
, &xn
))
339 if (ptr
&& dxp
!= NULL
&& dxp
->dx_ptrid
.di_type
== CTF_ERR
)
340 return (NULL
); /* no translation available to pointer type */
342 if (dxp
!= NULL
|| !(flags
& DT_XLATE_EXTERN
) ||
343 dtp
->dt_xlatemode
== DT_XL_STATIC
)
344 return (dxp
); /* we succeeded or not allowed to extern */
347 * If we get here, then we didn't find an existing translator, but the
348 * caller and xlatemode permit us to create an extern to a dynamic one.
350 src_dtt
.dtt_object
= dt_module_lookup_by_ctf(dtp
, src_ctfp
)->dm_name
;
351 src_dtt
.dtt_ctfp
= src_ctfp
;
352 src_dtt
.dtt_type
= src_type
;
354 dst_dtt
.dtt_object
= dt_module_lookup_by_ctf(dtp
, dst_ctfp
)->dm_name
;
355 dst_dtt
.dtt_ctfp
= dst_ctfp
;
356 dst_dtt
.dtt_type
= dst_type
;
358 return (dt_xlator_create(dtp
, &src_dtt
, &dst_dtt
, NULL
, NULL
, NULL
));
362 dt_xlator_lookup_id(dtrace_hdl_t
*dtp
, id_t id
)
364 assert(id
>= 0 && id
< dtp
->dt_xlatorid
);
365 return (dtp
->dt_xlatormap
[id
]);
369 dt_xlator_ident(dt_xlator_t
*dxp
, ctf_file_t
*ctfp
, ctf_id_t type
)
371 if (ctf_type_kind(ctfp
, ctf_type_resolve(ctfp
, type
)) == CTF_K_POINTER
)
372 return (&dxp
->dx_ptrid
);
374 return (&dxp
->dx_souid
);
378 dt_xlator_member(dt_xlator_t
*dxp
, const char *name
)
382 for (dnp
= dxp
->dx_members
; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
383 if (strcmp(dnp
->dn_membname
, name
) == 0)
391 dt_xlator_dynamic(const dt_xlator_t
*dxp
)
393 return (dxp
->dx_locals
== NULL
);