Skip to content

Commit 2aa4911

Browse files
committed
offset_of: Compile the offset properly
gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): Add proper handling of the node. * rust-backend.h (lookup_field): Declare it. * rust-gcc.cc (lookup_field): Add forked implementation from gcc/c/. gcc/testsuite/ChangeLog: * rust/execute/torture/offset_of1.rs: New test.
1 parent d4888e1 commit 2aa4911

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

gcc/rust/backend/rust-compile-expr.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-compile-expr.h"
20+
#include "rust-backend.h"
21+
#include "rust-compile-type.h"
2022
#include "rust-compile-struct-field-expr.h"
2123
#include "rust-compile-pattern.h"
2224
#include "rust-compile-resolve-path.h"
@@ -32,7 +34,9 @@
3234
#include "print-tree.h"
3335
#include "rust-hir-expr.h"
3436
#include "rust-system.h"
37+
#include "rust-tree.h"
3538
#include "rust-tyty.h"
39+
#include "tree-core.h"
3640

3741
namespace Rust {
3842
namespace Compile {
@@ -378,7 +382,26 @@ CompileExpr::visit (HIR::LlvmInlineAsm &expr)
378382
void
379383
CompileExpr::visit (HIR::OffsetOf &expr)
380384
{
381-
rust_unreachable ();
385+
TyTy::BaseType *type = nullptr;
386+
if (!ctx->get_tyctx ()->lookup_type (
387+
expr.get_type ().get_mappings ().get_hirid (), &type))
388+
{
389+
translated = error_mark_node;
390+
return;
391+
}
392+
393+
auto compiled_ty = TyTyResolveCompile::compile (ctx, type);
394+
395+
rust_assert (TREE_CODE (compiled_ty) == RECORD_TYPE);
396+
397+
// Create an identifier node for the field
398+
auto field_id = Backend::get_identifier_node (expr.get_field ().as_string ());
399+
400+
// And now look it up and get its value for `byte_position`
401+
auto field = Backend::lookup_field (compiled_ty, field_id);
402+
auto field_value = TREE_VALUE (field);
403+
404+
translated = byte_position (field_value);
382405
}
383406

384407
void

gcc/rust/rust-backend.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ tree goto_statement (tree, location_t);
397397
// recover.
398398
tree label_address (tree, location_t);
399399

400+
// Lookup a field from a type given its name.
401+
// Build the `component` tree with `Backend::get_identifier_node`.
402+
//
403+
// Forked from the C frontend.
404+
tree lookup_field (const_tree, tree);
405+
400406
// Functions.
401407

402408
// Bit flags to pass to the function method.

gcc/rust/rust-gcc.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,4 +2366,30 @@ write_global_definitions (const std::vector<tree> &type_decls,
23662366
delete[] defs;
23672367
}
23682368

2369+
tree
2370+
lookup_field (const_tree type, tree component)
2371+
{
2372+
tree field;
2373+
2374+
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
2375+
{
2376+
if (DECL_NAME (field) == NULL_TREE
2377+
&& RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
2378+
{
2379+
tree anon = lookup_field (TREE_TYPE (field), component);
2380+
2381+
if (anon)
2382+
return tree_cons (NULL_TREE, field, anon);
2383+
}
2384+
2385+
if (DECL_NAME (field) == component)
2386+
break;
2387+
}
2388+
2389+
if (field == NULL_TREE)
2390+
return NULL_TREE;
2391+
2392+
return tree_cons (NULL_TREE, field, NULL_TREE);
2393+
}
2394+
23692395
} // namespace Backend
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// { dg-do run { target x86_64*-*-* } }
2+
// { dg-additional-options "-frust-assume-builtin-offset-of" }
3+
4+
pub struct Foo {
5+
pub a: i32,
6+
pub b: i32,
7+
}
8+
9+
fn main() -> i32 {
10+
let a = offset_of!(Foo, a); // valid
11+
let b = offset_of!(Foo, b); // valid
12+
13+
let res = a + b - 4;
14+
15+
res as i32
16+
}

0 commit comments

Comments
 (0)