Skip to content

Commit f4e8afd

Browse files
Merge pull request #93 from GuillaumeGomez/type-attributes
Add support for type attributes and remove `gcc_jit_type_set_packed`
2 parents b22e988 + a2e4008 commit f4e8afd

11 files changed

Lines changed: 759 additions & 44 deletions

gcc/jit/dummy-frontend.cc

Lines changed: 319 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,19 @@ along with GCC; see the file COPYING3. If not see
4141

4242
using namespace gcc::jit;
4343

44+
/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
45+
#define DECL_C_BIT_FIELD(NODE) \
46+
(DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
47+
48+
/* This is needed as the function is used by the `size_int` macro. */
49+
tree
50+
size_int_kind (poly_int64 number, enum size_type_kind kind);
51+
4452
/* Attribute handling. */
4553

54+
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
55+
static tree handle_aligned_attribute (tree *node, tree name, tree args,
56+
int flags, bool *no_add_attrs);
4657
static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
4758
static tree handle_always_inline_attribute (tree *, tree, tree, int,
4859
bool *);
@@ -79,6 +90,16 @@ static tree ignore_attribute (tree *, tree, tree, int, bool *);
7990
#define ATTR_EXCL(name, function, type, variable) \
8091
{ name, function, type, variable }
8192

93+
/* Define attributes that are mutually exclusive with one another. */
94+
extern const struct attribute_spec::exclusions attr_aligned_exclusions[] =
95+
{
96+
/* Attribute name exclusion applies to:
97+
function, type, variable */
98+
ATTR_EXCL ("aligned", true, false, false),
99+
ATTR_EXCL ("packed", true, false, false),
100+
ATTR_EXCL (NULL, false, false, false)
101+
};
102+
82103
/* Define attributes that are mutually exclusive with one another. */
83104
static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
84105
{
@@ -171,6 +192,9 @@ static const attribute_spec jit_gnu_attributes[] =
171192
affects_type_identity, handler, exclude } */
172193
{ "alias", 1, 1, true, false, false, false,
173194
handle_alias_attribute, NULL },
195+
{ "aligned", 0, 1, false, false, false, false,
196+
handle_aligned_attribute,
197+
attr_aligned_exclusions },
174198
{ "always_inline", 0, 0, true, false, false, false,
175199
handle_always_inline_attribute,
176200
attr_always_inline_exclusions },
@@ -188,6 +212,7 @@ static const attribute_spec jit_gnu_attributes[] =
188212
handle_leaf_attribute, NULL },
189213
{ "malloc", 0, 0, true, false, false, false,
190214
handle_malloc_attribute, attr_alloc_exclusions },
215+
{ "may_alias", 0, 0, false, true, false, false, NULL, NULL },
191216
{ "noreturn", 0, 0, true, false, false, false,
192217
handle_noreturn_attribute,
193218
attr_noreturn_exclusions },
@@ -200,6 +225,9 @@ static const attribute_spec jit_gnu_attributes[] =
200225
handle_nonnull_attribute, NULL },
201226
{ "nothrow", 0, 0, true, false, false, false,
202227
handle_nothrow_attribute, NULL },
228+
{ "packed", 0, 0, false, false, false, false,
229+
handle_packed_attribute,
230+
attr_aligned_exclusions },
203231
{ "patchable_function_entry", 1, 2, true, false, false, false,
204232
handle_patchable_function_entry_attribute,
205233
NULL },
@@ -221,15 +249,15 @@ static const attribute_spec jit_gnu_attributes[] =
221249
handle_type_generic_attribute, NULL },
222250
{ "transaction_pure", 0, 0, false, true, true, false,
223251
handle_transaction_pure_attribute, NULL },
224-
{ "used", 0, 0, true, false, false, false,
225-
handle_used_attribute, NULL },
226-
{ "visibility", 1, 1, false, false, false, false,
227-
handle_visibility_attribute, NULL },
228-
{ "weak", 0, 0, true, false, false, false,
229-
handle_weak_attribute, NULL },
252+
{ "used", 0, 0, true, false, false, false,
253+
handle_used_attribute, NULL },
254+
{ "visibility", 1, 1, false, false, false, false,
255+
handle_visibility_attribute, NULL },
256+
{ "weak", 0, 0, true, false, false, false,
257+
handle_weak_attribute, NULL },
230258
/* For internal use only. The leading '*' both prevents its usage in
231259
source code and signals that it may be overridden by machine tables. */
232-
{ "*tm regparm", 0, 0, false, true, true, false,
260+
{ "*tm regparm", 0, 0, false, true, true, false,
233261
ignore_attribute, NULL },
234262
};
235263

@@ -1159,6 +1187,290 @@ handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
11591187
return NULL_TREE;
11601188
}
11611189

1190+
/* Handle a "packed" attribute; arguments as in
1191+
struct attribute_spec.handler. */
1192+
1193+
static tree
1194+
handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1195+
int flags, bool *no_add_attrs)
1196+
{
1197+
if (TYPE_P (*node))
1198+
{
1199+
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1200+
{
1201+
warning (OPT_Wattributes,
1202+
"%qE attribute ignored for type %qT", name, *node);
1203+
*no_add_attrs = true;
1204+
}
1205+
else
1206+
TYPE_PACKED (*node) = 1;
1207+
}
1208+
else if (TREE_CODE (*node) == FIELD_DECL)
1209+
{
1210+
if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
1211+
/* Still pack bitfields. */
1212+
&& ! DECL_C_BIT_FIELD (*node))
1213+
warning (OPT_Wattributes,
1214+
"%qE attribute ignored for field of type %qT",
1215+
name, TREE_TYPE (*node));
1216+
else
1217+
DECL_PACKED (*node) = 1;
1218+
}
1219+
/* We can't set DECL_PACKED for a VAR_DECL, because the bit is
1220+
used for DECL_REGISTER. It wouldn't mean anything anyway.
1221+
We can't set DECL_PACKED on the type of a TYPE_DECL, because
1222+
that changes what the typedef is typing. */
1223+
else
1224+
{
1225+
warning (OPT_Wattributes, "%qE attribute ignored", name);
1226+
*no_add_attrs = true;
1227+
}
1228+
1229+
return NULL_TREE;
1230+
}
1231+
1232+
1233+
static int
1234+
check_user_alignment (const_tree align, bool objfile, bool warn_zero)
1235+
{
1236+
if (error_operand_p (align))
1237+
return -1;
1238+
1239+
if (TREE_CODE (align) != INTEGER_CST
1240+
|| !INTEGRAL_TYPE_P (TREE_TYPE (align)))
1241+
{
1242+
error ("requested alignment is not an integer constant");
1243+
return -1;
1244+
}
1245+
1246+
if (integer_zerop (align))
1247+
{
1248+
if (warn_zero)
1249+
warning (OPT_Wattributes,
1250+
"requested alignment %qE is not a positive power of 2",
1251+
align);
1252+
return -1;
1253+
}
1254+
1255+
/* Log2 of the byte alignment ALIGN. */
1256+
int log2align;
1257+
if (tree_int_cst_sgn (align) == -1
1258+
|| (log2align = tree_log2 (align)) == -1)
1259+
{
1260+
error ("requested alignment %qE is not a positive power of 2",
1261+
align);
1262+
return -1;
1263+
}
1264+
1265+
if (objfile)
1266+
{
1267+
unsigned maxalign = MAX_OFILE_ALIGNMENT / BITS_PER_UNIT;
1268+
if (!tree_fits_uhwi_p (align) || tree_to_uhwi (align) > maxalign)
1269+
{
1270+
error ("requested alignment %qE exceeds object file maximum %u",
1271+
align, maxalign);
1272+
return -1;
1273+
}
1274+
}
1275+
1276+
if (log2align >= HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT)
1277+
{
1278+
error ("requested alignment %qE exceeds maximum %u",
1279+
align, 1U << (HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT - 1));
1280+
return -1;
1281+
}
1282+
1283+
return log2align;
1284+
}
1285+
1286+
/* Common codes shared by handle_warn_if_not_aligned_attribute and
1287+
handle_aligned_attribute. */
1288+
1289+
static tree
1290+
common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
1291+
bool *no_add_attrs,
1292+
bool warn_if_not_aligned_p)
1293+
{
1294+
tree decl = NULL_TREE;
1295+
tree *type = NULL;
1296+
bool is_type = false;
1297+
tree align_expr;
1298+
1299+
/* The last (already pushed) declaration with all validated attributes
1300+
merged in or the current about-to-be-pushed one if one hasn't been
1301+
yet. */
1302+
tree last_decl = node[1] ? node[1] : *node;
1303+
1304+
if (args)
1305+
{
1306+
align_expr = TREE_VALUE (args);
1307+
/* FIXME: Uncomment this code or find a way to use `default_conversion`.
1308+
if (align_expr && TREE_CODE (align_expr) != IDENTIFIER_NODE
1309+
&& TREE_CODE (align_expr) != FUNCTION_DECL)
1310+
align_expr = default_conversion (align_expr);*/
1311+
}
1312+
else
1313+
align_expr = size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT);
1314+
1315+
if (DECL_P (*node))
1316+
{
1317+
decl = *node;
1318+
type = &TREE_TYPE (decl);
1319+
is_type = TREE_CODE (*node) == TYPE_DECL;
1320+
}
1321+
else if (TYPE_P (*node))
1322+
type = node, is_type = true;
1323+
1324+
/* True to consider invalid alignments greater than MAX_OFILE_ALIGNMENT. */
1325+
bool objfile = (TREE_CODE (*node) == FUNCTION_DECL
1326+
|| (VAR_P (*node) && TREE_STATIC (*node)));
1327+
/* Log2 of specified alignment. */
1328+
int pow2align = check_user_alignment (align_expr, objfile,
1329+
/* warn_zero = */ true);
1330+
if (pow2align == -1)
1331+
{
1332+
*no_add_attrs = true;
1333+
return NULL_TREE;
1334+
}
1335+
1336+
/* The alignment in bits corresponding to the specified alignment. */
1337+
unsigned bitalign = (1U << pow2align) * BITS_PER_UNIT;
1338+
1339+
/* The alignment of the current declaration and that of the last
1340+
pushed declaration, determined on demand below. */
1341+
unsigned curalign = 0;
1342+
unsigned lastalign = 0;
1343+
1344+
/* True when SET_DECL_ALIGN() should be called for the decl when
1345+
*NO_ADD_ATTRS is false. */
1346+
bool set_align = true;
1347+
if (is_type)
1348+
{
1349+
if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1350+
/* OK, modify the type in place. */;
1351+
/* If we have a TYPE_DECL, then copy the type, so that we
1352+
don't accidentally modify a builtin type. See pushdecl. */
1353+
else if (decl && TREE_TYPE (decl) != error_mark_node
1354+
&& DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
1355+
{
1356+
tree tt = TREE_TYPE (decl);
1357+
*type = build_variant_type_copy (*type);
1358+
DECL_ORIGINAL_TYPE (decl) = tt;
1359+
TYPE_NAME (*type) = decl;
1360+
TREE_USED (*type) = TREE_USED (decl);
1361+
TREE_TYPE (decl) = *type;
1362+
}
1363+
else
1364+
*type = build_variant_type_copy (*type);
1365+
1366+
if (warn_if_not_aligned_p)
1367+
{
1368+
SET_TYPE_WARN_IF_NOT_ALIGN (*type, bitalign);
1369+
warn_if_not_aligned_p = false;
1370+
}
1371+
else
1372+
{
1373+
SET_TYPE_ALIGN (*type, bitalign);
1374+
TYPE_USER_ALIGN (*type) = 1;
1375+
}
1376+
}
1377+
else if (! VAR_OR_FUNCTION_DECL_P (decl)
1378+
&& TREE_CODE (decl) != FIELD_DECL)
1379+
{
1380+
error ("alignment may not be specified for %q+D", decl);
1381+
*no_add_attrs = true;
1382+
}
1383+
else if (TREE_CODE (decl) == FUNCTION_DECL
1384+
&& (((curalign = DECL_ALIGN (decl)) > bitalign)
1385+
| ((lastalign = DECL_ALIGN (last_decl)) > bitalign)))
1386+
{
1387+
/* Either a prior attribute on the same declaration or one
1388+
on a prior declaration of the same function specifies
1389+
stricter alignment than this attribute. */
1390+
bool note = (lastalign > curalign
1391+
|| (lastalign == curalign
1392+
&& (DECL_USER_ALIGN (last_decl)
1393+
> DECL_USER_ALIGN (decl))));
1394+
if (note)
1395+
curalign = lastalign;
1396+
1397+
curalign /= BITS_PER_UNIT;
1398+
unsigned newalign = bitalign / BITS_PER_UNIT;
1399+
1400+
auto_diagnostic_group d;
1401+
if ((DECL_USER_ALIGN (decl)
1402+
|| DECL_USER_ALIGN (last_decl)))
1403+
{
1404+
if (warning (OPT_Wattributes,
1405+
"ignoring attribute %<%E (%u)%> because it conflicts "
1406+
"with attribute %<%E (%u)%>",
1407+
name, newalign, name, curalign)
1408+
&& note)
1409+
inform (DECL_SOURCE_LOCATION (last_decl),
1410+
"previous declaration here");
1411+
/* Only reject attempts to relax/override an alignment
1412+
explicitly specified previously and accept declarations
1413+
that appear to relax the implicit function alignment for
1414+
the target. Both increasing and increasing the alignment
1415+
set by -falign-functions setting is permitted. */
1416+
*no_add_attrs = true;
1417+
}
1418+
else if (!warn_if_not_aligned_p)
1419+
{
1420+
/* Do not fail for attribute warn_if_not_aligned. Otherwise,
1421+
silently avoid applying the alignment to the declaration
1422+
because it's implicitly satisfied by the target. Apply
1423+
the attribute nevertheless so it can be retrieved by
1424+
__builtin_has_attribute. */
1425+
set_align = false;
1426+
}
1427+
}
1428+
else if (DECL_USER_ALIGN (decl)
1429+
&& DECL_ALIGN (decl) > bitalign)
1430+
/* C++-11 [dcl.align/4]:
1431+
1432+
When multiple alignment-specifiers are specified for an
1433+
entity, the alignment requirement shall be set to the
1434+
strictest specified alignment.
1435+
1436+
This formally comes from the c++11 specification but we are
1437+
doing it for the GNU attribute syntax as well. */
1438+
*no_add_attrs = true;
1439+
else if (warn_if_not_aligned_p
1440+
&& TREE_CODE (decl) == FIELD_DECL
1441+
&& !DECL_C_BIT_FIELD (decl))
1442+
{
1443+
SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign);
1444+
warn_if_not_aligned_p = false;
1445+
set_align = false;
1446+
}
1447+
1448+
if (warn_if_not_aligned_p)
1449+
{
1450+
error ("%<warn_if_not_aligned%> may not be specified for %q+D",
1451+
decl);
1452+
*no_add_attrs = true;
1453+
}
1454+
else if (!is_type && !*no_add_attrs && set_align)
1455+
{
1456+
SET_DECL_ALIGN (decl, bitalign);
1457+
DECL_USER_ALIGN (decl) = 1;
1458+
}
1459+
1460+
return NULL_TREE;
1461+
}
1462+
1463+
/* Handle a "aligned" attribute; arguments as in
1464+
struct attribute_spec.handler. */
1465+
1466+
tree
1467+
handle_aligned_attribute (tree *node, tree name, tree args,
1468+
int flags, bool *no_add_attrs)
1469+
{
1470+
return common_handle_aligned_attribute (node, name, args, flags,
1471+
no_add_attrs, false);
1472+
}
1473+
11621474
/* (end of attribute-handling). */
11631475

11641476
/* Language-dependent contents of a type. */

0 commit comments

Comments
 (0)