diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index b2549d48303b0..2b9becaddb549 100644 --- a/gcc/jit/dummy-frontend.cc +++ b/gcc/jit/dummy-frontend.cc @@ -518,12 +518,12 @@ struct GTY(()) lang_identifier /* The resulting tree type. */ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) -lang_tree_node -{ - union tree_node GTY((tag ("0"), - desc ("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag ("1"))) identifier; + chain_next ("(union lang_tree_node *) jit_tree_chain_next (&%h.generic)"))) lang_tree_node + { + union tree_node GTY ((tag ("0"), + desc ("tree_node_structure (&%h)"))) + generic; + struct lang_identifier GTY ((tag ("1"))) identifier; }; /* We don't use language_function. */ diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h index 3ff7447fbf3f6..f9aead2f66c75 100644 --- a/gcc/jit/jit-common.h +++ b/gcc/jit/jit-common.h @@ -93,6 +93,20 @@ const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1; End of comment for inclusion in the docs. */ +static inline tree +jit_tree_chain_next (tree t) +{ + /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different + kind of object, never a long chain of nodes. Prefer + TYPE_NEXT_VARIANT for types. */ + if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON)) + return TYPE_NEXT_VARIANT (t); + /* Otherwise, if there is TREE_CHAIN, return it. */ + if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON)) + return TREE_CHAIN (t); + return NULL; +} + namespace gcc { namespace jit { diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index 90bb163413461..25ea98f5fca61 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -405,7 +405,8 @@ playback::compound_type * playback::context:: new_compound_type (location *loc, const char *name, - bool is_struct) /* else is union */ + bool is_struct, /* else is union */ + bool is_packed) { gcc_assert (name); @@ -415,6 +416,9 @@ new_compound_type (location *loc, TYPE_NAME (t) = get_identifier (name); TYPE_SIZE (t) = 0; + if (is_packed) + TYPE_PACKED (t) = 1; + if (loc) set_tree_location (t, loc); @@ -422,7 +426,7 @@ new_compound_type (location *loc, } void -playback::compound_type::set_fields (const auto_vec *fields) +playback::compound_type::set_fields (const auto_vec *fields, bool is_packed) { /* Compare with c/c-decl.cc: finish_struct. */ tree t = as_tree (); @@ -439,6 +443,10 @@ playback::compound_type::set_fields (const auto_vec *fields) DECL_SIZE (x) = bitsize_int (width); DECL_BIT_FIELD (x) = 1; } + + if (is_packed && (DECL_BIT_FIELD (x) + || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)) + DECL_PACKED (x) = 1; fieldlist = chainon (x, fieldlist); } fieldlist = nreverse (fieldlist); diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 5ee7ee99c0e15..1568645c227d5 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -85,7 +85,8 @@ class context : public log_user compound_type * new_compound_type (location *loc, const char *name, - bool is_struct); /* else is union */ + bool is_struct, /* else is union */ + bool is_packed); type * new_function_type (type *return_type, @@ -472,7 +473,7 @@ class compound_type : public type : type (inner) {} - void set_fields (const auto_vec *fields); + void set_fields (const auto_vec *fields, bool is_packed); }; class field : public wrapper diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 31e486d19eaeb..934d8e62e8e13 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -845,7 +845,7 @@ recording::context::new_array_type (recording::location *loc, recording::type *element_type, int num_elements) { - if (struct_ *s = element_type->dyn_cast_struct ()) + /*if (struct_ *s = element_type->dyn_cast_struct ()) if (!s->get_fields ()) { add_error (NULL, @@ -853,7 +853,7 @@ recording::context::new_array_type (recording::location *loc, " until the fields have been set", s->get_name ()->c_str ()); return NULL; - } + }*/ recording::type *result = new recording::array_type (this, loc, element_type, num_elements); record (result); @@ -2385,6 +2385,12 @@ recording::type::get_aligned (size_t alignment_in_bytes) return result; } +void +recording::type::set_packed () +{ + m_packed = true; +} + /* Given a type, get a vector version of the type. Implements the post-error-checking part of @@ -3578,7 +3584,8 @@ recording::struct_::replay_into (replayer *r) set_playback_obj ( r->new_compound_type (playback_location (r, get_loc ()), get_name ()->c_str (), - true /* is_struct */)); + true, /* is_struct */ + m_packed)); } const char * @@ -3632,7 +3639,8 @@ recording::union_::replay_into (replayer *r) set_playback_obj ( r->new_compound_type (playback_location (r, get_loc ()), get_name ()->c_str (), - false /* is_struct */)); + false, /* is_struct */ + m_packed)); } /* Implementation of recording::memento::make_debug_string for @@ -3703,7 +3711,7 @@ recording::fields::replay_into (replayer *) playback_fields.create (m_fields.length ()); for (unsigned i = 0; i < m_fields.length (); i++) playback_fields.safe_push (m_fields[i]->playback_field ()); - m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields); + m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields, m_struct_or_union->m_packed); } /* Override the default implementation of diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index a1ac398ce640e..64d7e81248c42 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -545,6 +545,8 @@ class type : public memento type *get_aligned (size_t alignment_in_bytes); type *get_vector (size_t num_units); + void set_packed (); + /* Get the type obtained when dereferencing this type. This will return NULL if it's not valid to dereference this type. @@ -613,9 +615,13 @@ class type : public memento protected: type (context *ctxt) : memento (ctxt), + m_packed (false), m_pointer_to_this_type (NULL) {} +public: + bool m_packed; + private: type *m_pointer_to_this_type; }; diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 5c14dfeb2da0d..3c8226e032288 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -981,6 +981,7 @@ size_t gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type) { RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type"); + RETURN_VAL_IF_FAIL (struct_type->get_fields (), 0, NULL, NULL, "NULL fields"); return struct_type->get_fields ()->length (); } @@ -4016,6 +4017,14 @@ gcc_jit_type_get_aligned (gcc_jit_type *type, return (gcc_jit_type *)type->get_aligned (alignment_in_bytes); } +void +gcc_jit_type_set_packed (gcc_jit_type *type) +{ + RETURN_IF_FAIL (type, NULL, NULL, "NULL type"); + + type->set_packed (); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 424d497cb55e9..deafb7da7fc3c 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -2019,6 +2019,10 @@ gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type); extern gcc_jit_type * gcc_jit_type_unqualified (gcc_jit_type *type); +/* Given type "T", get type "T __attribute__ ((packed))". */ +extern void +gcc_jit_type_set_packed (gcc_jit_type *type); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index e7a0e36118812..814e790b89441 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -278,3 +278,8 @@ LIBGCCJIT_ABI_25 { gcc_jit_context_new_vector_constructor; gcc_jit_context_new_vector_access; } LIBGCCJIT_ABI_24; + +LIBGCCJIT_ABI_26 { + global: + gcc_jit_type_set_packed; +} LIBGCCJIT_ABI_25;