Skip to content

Clang: __builtin_offsetof ignores attribute preserve_access_index #61904

Open
@j-piecuch

Description

@j-piecuch

https://godbolt.org/z/Y5Y8xWr1v

Source:

#include <stddef.h>

struct s {
    int bar;
    int foo;
} __attribute__((preserve_access_index));

#define normal_offsetof(type, member)                              \
  ({                                                              \
    type *__base = NULL;                                          \
    ((unsigned long)(&__base->member)); \
  })

#define core_offsetof(type, member)                               \
  ({                                                              \
    type *__base = NULL;                                          \
    ((unsigned long)__builtin_preserve_access_index(&__base->member)); \
  })

unsigned long using_builtin_offsetof(int *p) {
    return __builtin_offsetof(struct s, foo);
}

unsigned long using_normal_offsetof(int *p) {
    return normal_offsetof(struct s, foo);
}

unsigned long using_core_offsetof(int *p) {
    return core_offsetof(struct s, foo);
}

LLVM IR:

@"llvm.s:0:4$0:1" = external global i64, !llvm.preserve.access.index !0 #0

define dso_local i64 @using_builtin_offsetof(ptr nocapture noundef readnone %0) local_unnamed_addr #1 !dbg !15 {
  call void @llvm.dbg.value(metadata ptr %0, metadata !20, metadata !DIExpression()), !dbg !21
  ret i64 4, !dbg !22
}

define dso_local i64 @using_normal_offsetof(ptr nocapture noundef readnone %0) local_unnamed_addr #2 !dbg !23 {
  call void @llvm.dbg.value(metadata ptr %0, metadata !25, metadata !DIExpression()), !dbg !29
  call void @llvm.dbg.value(metadata ptr null, metadata !26, metadata !DIExpression()), !dbg !30
  %2 = load i64, ptr @"llvm.s:0:4$0:1", align 8
  %3 = getelementptr i8, ptr null, i64 %2
  %4 = tail call ptr @llvm.bpf.passthrough.p0.p0(i32 0, ptr %3)
  %5 = ptrtoint ptr %4 to i64, !dbg !31
  ret i64 %5, !dbg !32
}

define dso_local i64 @using_core_offsetof(ptr nocapture noundef readnone %0) local_unnamed_addr #2 !dbg !33 {
  call void @llvm.dbg.value(metadata ptr %0, metadata !35, metadata !DIExpression()), !dbg !38
  call void @llvm.dbg.value(metadata ptr null, metadata !36, metadata !DIExpression()), !dbg !39
  %2 = load i64, ptr @"llvm.s:0:4$0:1", align 8
  %3 = getelementptr i8, ptr null, i64 %2
  %4 = tail call ptr @llvm.bpf.passthrough.p0.p0(i32 1, ptr %3)
  %5 = ptrtoint ptr %4 to i64, !dbg !40
  ret i64 %5, !dbg !41
}

declare ptr @llvm.bpf.passthrough.p0.p0(i32, ptr) #3

declare void @llvm.dbg.value(metadata, metadata, metadata) #4

attributes #0 = { "btf_ama" }
attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="v2" }
attributes #2 = { nofree nosync nounwind memory(read, argmem: none, inaccessiblemem: none) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="v2" }
attributes #3 = { nofree nosync nounwind memory(none) }
attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

Expected behavior: LLVM IR for using_builtin_offsetof should cause the backend to generate relocations for the offset.

My suspicion is that IntExprEvaluator::VisitOffsetOfExpr() is completely oblivious to the preserve_access_index attribute and happily evaluates the expression to a constant.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions