From: Arthur Cohen <[email protected]>
gcc/rust/ChangeLog:
* backend/rust-compile-intrinsic.cc: Register new handler.
* backend/rust-intrinsic-handlers.cc (ptr_offset_from): New function.
* backend/rust-intrinsic-handlers.h (ptr_offset_from): Likewise.
* typecheck/rust-hir-type-check-intrinsic.cc: Register new entry for
ptr_offset_from.
* util/rust-intrinsic-values.h: Likewise.
gcc/testsuite/ChangeLog:
* rust/execute/torture/ptr_offset_from.rs: New test.
Tested on x86_64-pc-linux-gnu.
---
gcc/rust/backend/rust-compile-intrinsic.cc | 1 +
gcc/rust/backend/rust-intrinsic-handlers.cc | 40 +++++++++++++++++++
gcc/rust/backend/rust-intrinsic-handlers.h | 2 +
.../rust-hir-type-check-intrinsic.cc | 4 ++
gcc/rust/util/rust-intrinsic-values.h | 2 +
.../rust/execute/torture/ptr_offset_from.rs | 30 ++++++++++++++
6 files changed, 79 insertions(+)
create mode 100644 gcc/testsuite/rust/execute/torture/ptr_offset_from.rs
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 862d9a3adb7..8b98d35416d 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -234,6 +234,7 @@ static const std::map<std::string, Intrinsic::CompileFn>
intrinsics = {
{IValue::ASSERT_ZERO_VALID, handlers::type_assert (TyAssert::ZeroValid)},
{IValue::ASSERT_INHABITED, handlers::type_assert (TyAssert::Inhabited)},
{IValue::ASSERT_UNINIT_VALID, handlers::type_assert (TyAssert::UninitValid)},
+ {IValue::PTR_OFFSET_FROM, handlers::ptr_offset_from},
};
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 74d278d3388..d4ef4a9c728 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -27,6 +27,7 @@
#include "rust-diagnostics.h"
#include "rust-location.h"
#include "rust-constexpr.h"
+#include "rust-operators.h"
#include "rust-session-manager.h"
#include "rust-tree.h"
#include "rust-tyty.h"
@@ -2215,6 +2216,45 @@ breakpoint (IntrinsicCtx &ctx)
TREE_SIDE_EFFECTS (ctx.fn) = 1;
}
+void
+ptr_offset_from (IntrinsicCtx &ctx)
+{
+ // Per offset_from's documentation
+ // https://doc.rust-lang.org/std/primitive.pointer.html#method.offset_from
+ //
+ // This calculates the distance between two pointers in terms of units of `T`
+ // - the distance in bytes divided by `size_of::<T>()`
+
+ auto ¶m_mapping = ctx.fntype.get_substs ().at (0);
+ auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
+ tree ty = TyTyResolveCompile::compile (ctx.inner (), resolved_tyty);
+
+ auto pointee_size_unsigned = TYPE_SIZE_UNIT (ty);
+ auto pointee_size
+ = Backend::convert_expression (signed_size_type_node,
pointee_size_unsigned,
+ ctx.loc);
+
+ auto addr = Backend::var_expression (ctx.param_vars[0], ctx.loc);
+ auto base = Backend::var_expression (ctx.param_vars[1], ctx.loc);
+
+ // Convert the pointers to integers
+ auto addr_int
+ = Backend::convert_expression (signed_size_type_node, addr, ctx.loc);
+ auto base_int
+ = Backend::convert_expression (signed_size_type_node, base, ctx.loc);
+
+ auto byte_diff = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::SUBTRACT, addr_int, base_int, ctx.loc);
+
+ auto result = build2_loc (ctx.loc, EXACT_DIV_EXPR, signed_size_type_node,
+ byte_diff, pointee_size);
+
+ auto return_stmt = Backend::return_statement (ctx.fn, result, ctx.loc);
+
+ ctx.add_statement (return_stmt);
+}
+
} // namespace handlers
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h
b/gcc/rust/backend/rust-intrinsic-handlers.h
index b57485d130c..7e5691041b5 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -221,6 +221,8 @@ Intrinsic::CompileFn type_assert (TyAssert assert);
void breakpoint (IntrinsicCtx &ctx);
+void ptr_offset_from (IntrinsicCtx &ctx);
+
} // namespace handlers
} // namespace Compile
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index afa633c3852..3139bf5d45b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -537,6 +537,10 @@ const std::unordered_map<std::string, IntrinsicRules>
// fn nontemporal_store<T>(ptr: *mut T, value: T)
{IValue::NONTEMPORAL_STORE,
{1, {IRT::MutPtrFirstGeneric, IRT::FirstGeneric}, IRT::Unit}},
+
+ // fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
+ {IValue::PTR_OFFSET_FROM,
+ {1, {IRT::ConstPtrFirstGeneric, IRT::ConstPtrFirstGeneric}, IRT::Isize}},
};
IntrinsicCheckResult
diff --git a/gcc/rust/util/rust-intrinsic-values.h
b/gcc/rust/util/rust-intrinsic-values.h
index 1bd5d16527c..f8067a62a46 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -286,6 +286,8 @@ public:
static constexpr auto &EXACT_DIV = "exact_div";
static constexpr auto &NONTEMPORAL_STORE = "nontemporal_store";
+
+ static constexpr auto &PTR_OFFSET_FROM = "ptr_offset_from";
};
} // namespace Values
} // namespace Rust
diff --git a/gcc/testsuite/rust/execute/torture/ptr_offset_from.rs
b/gcc/testsuite/rust/execute/torture/ptr_offset_from.rs
new file mode 100644
index 00000000000..d884cc8ff23
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/ptr_offset_from.rs
@@ -0,0 +1,30 @@
+#![feature(no_core)]
+#![feature(intrinsics)]
+#![feature(lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "rust-intrinsic" {
+ fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
+ fn size_of<T>() -> usize;
+}
+
+fn main() -> i32 {
+ let value = 0;
+
+ let first = &value as *const i32;
+
+ // Crimes? A lil bit of crimes?
+ let last = first as usize;
+
+ let last = last + 8 * size_of::<i32>();
+
+ let first = first as *const i32;
+ let last = last as *const i32;
+
+ let offset = unsafe { ptr_offset_from(last, first) };
+
+ offset as i32 - 8
+}
--
2.55.0