Open
Description
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.