aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-resolve-path.cc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-12-14 18:10:42 +0000
committerPhilip Herron <philip.herron@embecosm.com>2021-12-16 10:17:08 +0000
commite0588300adc00872b0e818477dba614348d2cb02 (patch)
treea696b3458140310c223e519b0b53d4481dc2c1de /gcc/rust/backend/rust-compile-resolve-path.cc
parent3629645386ad503606f29f95c2e16d0600df6e20 (diff)
downloadgcc-e0588300adc00872b0e818477dba614348d2cb02.zip
gcc-e0588300adc00872b0e818477dba614348d2cb02.tar.gz
gcc-e0588300adc00872b0e818477dba614348d2cb02.tar.bz2
Add enum code generation
This adds a naieve first pass approach to enum type code generation. The original idea was to use GCC's QUAL_UNION_TYPE but I have ran into issues with the DECL_QUALIFIER as my understanding of how this works is incorrect. This takes an enum such as: ```rust enum AnEnum { A, B, C (char), D (x: i64, y: i64), } ``` And turns this into one big union consisting of all fields as RECORD_TYPES. ```c union AnEnum { record A { RUST$ENUM$DISR }; record B { RUST$ENUM$DISR }; record C { RUST$ENUM$DISR, char }; record D { RUST$ENUM$DISR, i64, i64}; } ``` see: https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241 With the RUST$ENUM$DISR being the first field in all of the records this means the alignment allows for indirect memory access of the struct to use it as a qualifier field to figure out which variant is currently in use. The data-less varients use their generated discriminat value during type-checking the data variants use their HIR ID for their discriminant. This will likely get redone to get improved GDB integration/updated to use the QUAL_UNION_TYPE when we learn how to do this properly. Fixes #79
Diffstat (limited to 'gcc/rust/backend/rust-compile-resolve-path.cc')
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc49
1 files changed, 43 insertions, 6 deletions
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index cb3f0df..07133b9 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -45,6 +45,10 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
const Analysis::NodeMapping &mappings,
Location expr_locus, bool is_qualified_path)
{
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
+ rust_assert (ok);
+
// need to look up the reference for this identifier
NodeId ref_node_id = UNKNOWN_NODEID;
if (ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
@@ -63,8 +67,44 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
// in that case the caller should attempt ResolvePathType::Compile
if (ref_node_id == UNKNOWN_NODEID)
{
- rust_error_at (expr_locus, "unknown nodeid for path expr");
- return ctx->get_backend ()->error_expression ();
+ // it might be an enum data-less enum variant
+ if (lookup->get_kind () != TyTy::TypeKind::ADT)
+ return ctx->get_backend ()->error_expression ();
+
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
+ if (!adt->is_enum ())
+ return ctx->get_backend ()->error_expression ();
+
+ HirId variant_id;
+ if (!ctx->get_tyctx ()->lookup_variant_definition (mappings.get_hirid (),
+ &variant_id))
+ return ctx->get_backend ()->error_expression ();
+
+ int union_disriminator = -1;
+ TyTy::VariantDef *variant = nullptr;
+ if (!adt->lookup_variant_by_id (variant_id, &variant,
+ &union_disriminator))
+ return ctx->get_backend ()->error_expression ();
+
+ // FIXME should really return error_mark_node and or rust_internal_error
+ // error_mark_node
+ rust_assert (variant->get_variant_type ()
+ == TyTy::VariantDef::VariantType::NUM);
+
+ // we need the actual gcc type
+ tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
+
+ // make the ctor for the union
+ mpz_t val;
+ mpz_init_set_ui (val, variant->get_discriminant ());
+ tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
+ tree qualifier
+ = double_int_to_tree (t, mpz_get_double_int (t, val, true));
+
+ return ctx->get_backend ()->constructor_expression (compiled_adt_type,
+ true, {qualifier},
+ union_disriminator,
+ expr_locus);
}
HirId ref;
@@ -86,9 +126,6 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
return ctx->get_backend ()->var_expression (var, expr_locus);
// it might be a function call
- TyTy::BaseType *lookup = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
- rust_assert (ok);
if (lookup->get_kind () == TyTy::TypeKind::FNDEF)
{
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
@@ -102,7 +139,7 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
// let the query system figure it out
return query_compile (ref, lookup, final_segment, mappings, expr_locus,
is_qualified_path);
-}
+} // namespace Compile
tree
ResolvePathRef::query_compile (HirId ref, TyTy::BaseType *lookup,