Skip to content

Commit

Permalink
Merge pull request #48 from rust-lang/feature/alignof
Browse files Browse the repository at this point in the history
Add ability to get the alignment of a type
  • Loading branch information
antoyo authored Apr 4, 2024
2 parents 2cf6ca7 + 8e86887 commit fd61715
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 15 deletions.
14 changes: 14 additions & 0 deletions gcc/jit/docs/topics/expressions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ Simple expressions
sizeof (type)
.. function:: gcc_jit_rvalue *\
gcc_jit_context_new_alignof (gcc_jit_context *ctxt, \
gcc_jit_type *type)
Generate an rvalue that is equal to the alignment of ``type``.

The parameter ``type`` must be non-NULL.

This is equivalent to this C code:

.. code-block:: c
_Alignof (type)
Constructor expressions
***********************

Expand Down
11 changes: 11 additions & 0 deletions gcc/jit/jit-playback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,17 @@ new_sizeof (type *type)

/* Construct a playback::rvalue instance (wrapping a tree). */

playback::rvalue *
playback::context::
new_alignof (type *type)
{
int alignment = TYPE_ALIGN (type->as_tree ()) / BITS_PER_UNIT;
tree inner = build_int_cst (integer_type_node, alignment);
return new rvalue (this, inner);
}

/* Construct a playback::rvalue instance (wrapping a tree). */

playback::rvalue *
playback::context::
new_string_literal (const char *value)
Expand Down
3 changes: 3 additions & 0 deletions gcc/jit/jit-playback.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class context : public log_user
rvalue *
new_sizeof (type *type);

rvalue *
new_alignof (type *type);

rvalue *
new_string_literal (const char *value);

Expand Down
67 changes: 56 additions & 11 deletions gcc/jit/jit-recording.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ recording::context::new_global_init_rvalue (lvalue *variable,
gbl->set_rvalue_init (init); /* Needed by the global for write dump. */
}

/* Create a recording::memento_of_sizeof instance and add it
/* Create a recording::memento_of_typeinfo instance and add it
to this context's list of mementos.

Implements the post-error-checking part of
Expand All @@ -1144,7 +1144,22 @@ recording::rvalue *
recording::context::new_sizeof (recording::type *type)
{
recording::rvalue *result =
new memento_of_sizeof (this, NULL, type);
new memento_of_typeinfo (this, NULL, type, TYPE_INFO_SIZE_OF);
record (result);
return result;
}

/* Create a recording::memento_of_typeinfo instance and add it
to this context's list of mementos.

Implements the post-error-checking part of
gcc_jit_context_new_alignof. */

recording::rvalue *
recording::context::new_alignof (recording::type *type)
{
recording::rvalue *result =
new memento_of_typeinfo (this, NULL, type, TYPE_INFO_ALIGN_OF);
record (result);
return result;
}
Expand Down Expand Up @@ -5805,39 +5820,69 @@ memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)

} // namespace recording

/* The implementation of class gcc::jit::recording::memento_of_sizeof. */
/* The implementation of class gcc::jit::recording::memento_of_typeinfo. */

/* Implementation of pure virtual hook recording::memento::replay_into
for recording::memento_of_sizeof. */
for recording::memento_of_typeinfo. */

void
recording::memento_of_sizeof::replay_into (replayer *r)
recording::memento_of_typeinfo::replay_into (replayer *r)
{
set_playback_obj (r->new_sizeof (m_type->playback_type ()));
switch (m_info_type)
{
case TYPE_INFO_ALIGN_OF:
set_playback_obj (r->new_alignof (m_type->playback_type ()));
break;
case TYPE_INFO_SIZE_OF:
set_playback_obj (r->new_sizeof (m_type->playback_type ()));
break;
}
}

/* Implementation of recording::memento::make_debug_string for
sizeof expressions. */

recording::string *
recording::memento_of_sizeof::make_debug_string ()
recording::memento_of_typeinfo::make_debug_string ()
{
const char* ident;
switch (m_info_type)
{
case TYPE_INFO_ALIGN_OF:
ident = "_Alignof";
break;
case TYPE_INFO_SIZE_OF:
ident = "sizeof";
break;
}
return string::from_printf (m_ctxt,
"sizeof (%s)",
"%s (%s)",
ident,
m_type->get_debug_string ());
}

/* Implementation of recording::memento::write_reproducer for sizeof
expressions. */

void
recording::memento_of_sizeof::write_reproducer (reproducer &r)
recording::memento_of_typeinfo::write_reproducer (reproducer &r)
{
const char* type;
switch (m_info_type)
{
case TYPE_INFO_ALIGN_OF:
type = "align";
break;
case TYPE_INFO_SIZE_OF:
type = "size";
break;
}
const char *id = r.make_identifier (this, "rvalue");
r.write (" gcc_jit_rvalue *%s =\n"
" gcc_jit_context_new_sizeof (%s, /* gcc_jit_context *ctxt */\n"
" %s); /* gcc_jit_type *type */\n",
" gcc_jit_context_new_%sof (%s, /* gcc_jit_context *ctxt */\n"
" (gcc_jit_type *) %s); /* gcc_jit_type *type */\n",
id,
type,
r.get_identifier (get_context ()),
r.get_identifier (m_type));
}
Expand Down
19 changes: 15 additions & 4 deletions gcc/jit/jit-recording.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class reproducer;

namespace recording {

enum type_info_type {
TYPE_INFO_ALIGN_OF,
TYPE_INFO_SIZE_OF,
};

playback::location *
playback_location (replayer *r, location *loc);

Expand Down Expand Up @@ -181,6 +186,9 @@ class context : public log_user
rvalue *
new_sizeof (type *type);

rvalue *
new_alignof (type *type);

rvalue *
new_string_literal (const char *value);

Expand Down Expand Up @@ -1814,14 +1822,16 @@ class memento_of_new_rvalue_from_const : public rvalue
HOST_TYPE m_value;
};

class memento_of_sizeof : public rvalue
class memento_of_typeinfo : public rvalue
{
public:
memento_of_sizeof (context *ctxt,
memento_of_typeinfo (context *ctxt,
location *loc,
type *type)
type *type,
type_info_type type_info)
: rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_INT)),
m_type (type) {}
m_type (type),
m_info_type (type_info) {}

void replay_into (replayer *r) final override;

Expand All @@ -1837,6 +1847,7 @@ class memento_of_sizeof : public rvalue

private:
type *m_type;
type_info_type m_info_type;
};

class memento_of_new_string_literal : public rvalue
Expand Down
18 changes: 18 additions & 0 deletions gcc/jit/libgccjit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,24 @@ gcc_jit_context_new_sizeof (gcc_jit_context *ctxt,
->new_sizeof (type));
}

/* Public entrypoint. See description in libgccjit.h.

After error-checking, the real work is done by the
gcc::jit::recording::context::new_alignof method in
jit-recording.cc. */

gcc_jit_rvalue *
gcc_jit_context_new_alignof (gcc_jit_context *ctxt,
gcc_jit_type *type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
RETURN_NULL_IF_FAIL (type, ctxt, NULL, "NULL type");
JIT_LOG_FUNC (ctxt->get_logger ());

return ((gcc_jit_rvalue *)ctxt
->new_alignof (type));
}

/* Public entrypoint. See description in libgccjit.h.

After error-checking, the real work is done by the
Expand Down
13 changes: 13 additions & 0 deletions gcc/jit/libgccjit.h
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,19 @@ extern gcc_jit_rvalue *
gcc_jit_context_new_sizeof (gcc_jit_context *ctxt,
gcc_jit_type *type);

#define LIBGCCJIT_HAVE_gcc_jit_context_new_alignof

/* Generates an rvalue that is equal to the alignment of type.

This API entrypoint was added in LIBGCCJIT_ABI_38; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_alignof */

extern gcc_jit_rvalue *
gcc_jit_context_new_alignof (gcc_jit_context *ctxt,
gcc_jit_type *type);


/* String literals. */
extern gcc_jit_rvalue *
gcc_jit_context_new_string_literal (gcc_jit_context *ctxt,
Expand Down
5 changes: 5 additions & 0 deletions gcc/jit/libgccjit.map
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,8 @@ LIBGCCJIT_ABI_37 {
gcc_jit_function_set_location;
gcc_jit_rvalue_set_location;
} LIBGCCJIT_ABI_36;

LIBGCCJIT_ABI_38 {
global:
gcc_jit_context_new_alignof;
} LIBGCCJIT_ABI_37;
10 changes: 10 additions & 0 deletions gcc/testsuite/jit.dg/all-non-failing-tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
#undef create_code
#undef verify_code

/* test-alignof.c */
#define create_code create_code_alignof
#define verify_code verify_code_alignof
#include "test-alignof.c"
#undef create_code
#undef verify_code

/* test-always_inline-attribute.c: This can't be in the testcases array as it needs
the `-O0` flag. */

Expand Down Expand Up @@ -455,6 +462,9 @@ const struct testcase testcases[] = {
{"accessing_union",
create_code_accessing_union,
verify_code_accessing_union},
{"alignof",
create_code_alignof,
verify_code_alignof},
{"alignment",
create_code_alignment,
verify_code_alignment},
Expand Down
69 changes: 69 additions & 0 deletions gcc/testsuite/jit.dg/test-alignof.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "libgccjit.h"

#include "harness.h"

void
create_code (gcc_jit_context *ctxt, void *user_data)
{
/* Let's try to inject the equivalent of:
int
my_alignof ()
{
return _Alignof(int32_t);
}
*/
gcc_jit_type *int32 =
gcc_jit_context_get_int_type (ctxt, 4, 1);
gcc_jit_type *int64 =
gcc_jit_context_get_int_type (ctxt, 8, 1);
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);

gcc_jit_function *func =
gcc_jit_context_new_function (ctxt,
NULL,
GCC_JIT_FUNCTION_EXPORTED,
int_type,
"my_alignof",
0, NULL, 0);

gcc_jit_block *initial =
gcc_jit_function_new_block (func, "initial");

gcc_jit_field *field1 =
gcc_jit_context_new_field (ctxt, NULL, int32, "int32");
gcc_jit_field *field2 =
gcc_jit_context_new_field (ctxt, NULL, int64, "int64");

gcc_jit_field *fields[] = {
field1,
field2,
};

gcc_jit_struct *struct_type =
gcc_jit_context_new_struct_type (
ctxt,
NULL,
"ints",
2, fields);

gcc_jit_block_end_with_return(initial, NULL,
gcc_jit_context_new_alignof(ctxt, gcc_jit_struct_as_type (struct_type)));
}

void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
typedef int (*my_alignof_type) ();
CHECK_NON_NULL (result);
my_alignof_type my_alignof =
(my_alignof_type)gcc_jit_result_get_code (result, "my_alignof");
CHECK_NON_NULL (my_alignof);
int val = my_alignof ();
CHECK_VALUE (val, 8);
}

0 comments on commit fd61715

Please sign in to comment.