diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-12-14 18:10:42 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-12-16 10:17:08 +0000 |
commit | e0588300adc00872b0e818477dba614348d2cb02 (patch) | |
tree | a696b3458140310c223e519b0b53d4481dc2c1de /gcc/rust/backend/rust-compile-resolve-path.cc | |
parent | 3629645386ad503606f29f95c2e16d0600df6e20 (diff) | |
download | gcc-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.cc | 49 |
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, |