Commit 294ee1bbc9
Changed files (6)
src
src/translate_c/ast.zig
@@ -148,6 +148,8 @@ pub const Node = extern union {
ptr_cast,
/// @divExact(lhs, rhs)
div_exact,
+ /// @byteOffsetOf(lhs, rhs)
+ byte_offset_of,
negate,
negate_wrap,
@@ -303,6 +305,7 @@ pub const Node = extern union {
.std_mem_zeroinit,
.ptr_cast,
.div_exact,
+ .byte_offset_of,
=> Payload.BinOp,
.integer_literal,
@@ -1135,6 +1138,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.div_exact).?.data;
return renderBuiltinCall(c, "@divExact", &.{ payload.lhs, payload.rhs });
},
+ .byte_offset_of => {
+ const payload = node.castTag(.byte_offset_of).?.data;
+ return renderBuiltinCall(c, "@byteOffsetOf", &.{ payload.lhs, payload.rhs });
+ },
.sizeof => {
const payload = node.castTag(.sizeof).?.data;
return renderBuiltinCall(c, "@sizeOf", &.{payload});
@@ -2001,6 +2008,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.array_type,
.bool_to_int,
.div_exact,
+ .byte_offset_of,
=> {
// no grouping needed
return renderNode(c, node);
src/clang.zig
@@ -432,6 +432,9 @@ pub const FieldDecl = opaque {
pub const getLocation = ZigClangFieldDecl_getLocation;
extern fn ZigClangFieldDecl_getLocation(*const FieldDecl) SourceLocation;
+
+ pub const getParent = ZigClangFieldDecl_getParent;
+ extern fn ZigClangFieldDecl_getParent(*const FieldDecl) ?*const RecordDecl;
};
pub const FileID = opaque {};
@@ -593,6 +596,34 @@ pub const TypeOfExprType = opaque {
extern fn ZigClangTypeOfExprType_getUnderlyingExpr(*const TypeOfExprType) *const Expr;
};
+pub const OffsetOfNode = opaque {
+ pub const getKind = ZigClangOffsetOfNode_getKind;
+ extern fn ZigClangOffsetOfNode_getKind(*const OffsetOfNode) OffsetOfNode_Kind;
+
+ pub const getArrayExprIndex = ZigClangOffsetOfNode_getArrayExprIndex;
+ extern fn ZigClangOffsetOfNode_getArrayExprIndex(*const OffsetOfNode) c_uint;
+
+ pub const getField = ZigClangOffsetOfNode_getField;
+ extern fn ZigClangOffsetOfNode_getField(*const OffsetOfNode) *FieldDecl;
+};
+
+pub const OffsetOfExpr = opaque {
+ pub const getNumComponents = ZigClangOffsetOfExpr_getNumComponents;
+ extern fn ZigClangOffsetOfExpr_getNumComponents(*const OffsetOfExpr) c_uint;
+
+ pub const getNumExpressions = ZigClangOffsetOfExpr_getNumExpressions;
+ extern fn ZigClangOffsetOfExpr_getNumExpressions(*const OffsetOfExpr) c_uint;
+
+ pub const getIndexExpr = ZigClangOffsetOfExpr_getIndexExpr;
+ extern fn ZigClangOffsetOfExpr_getIndexExpr(*const OffsetOfExpr, idx: c_uint) *const Expr;
+
+ pub const getComponent = ZigClangOffsetOfExpr_getComponent;
+ extern fn ZigClangOffsetOfExpr_getComponent(*const OffsetOfExpr, idx: c_uint) *const OffsetOfNode;
+
+ pub const getBeginLoc = ZigClangOffsetOfExpr_getBeginLoc;
+ extern fn ZigClangOffsetOfExpr_getBeginLoc(*const OffsetOfExpr) SourceLocation;
+};
+
pub const MemberExpr = opaque {
pub const getBase = ZigClangMemberExpr_getBase;
extern fn ZigClangMemberExpr_getBase(*const MemberExpr) *const Expr;
@@ -1655,6 +1686,13 @@ pub const UnaryExprOrTypeTrait_Kind = extern enum {
PreferredAlignOf,
};
+pub const OffsetOfNode_Kind = extern enum {
+ Array,
+ Field,
+ Identifier,
+ Base,
+};
+
pub const Stage2ErrorMsg = extern struct {
filename_ptr: ?[*]const u8,
filename_len: usize,
src/translate_c.zig
@@ -1069,12 +1069,64 @@ fn transStmt(
const expr = try transExpr(c, scope, source_expr, .used);
return maybeSuppressResult(c, scope, result_used, expr);
},
+ .OffsetOfExprClass => return transOffsetOfExpr(c, scope, @ptrCast(*const clang.OffsetOfExpr, stmt), result_used),
else => {
return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});
},
}
}
+/// Translate a "simple" offsetof expression containing exactly one component,
+/// when that component is of kind .Field - e.g. offsetof(mytype, myfield)
+fn transSimpleOffsetOfExpr(
+ c: *Context,
+ scope: *Scope,
+ expr: *const clang.OffsetOfExpr,
+) TransError!Node {
+ assert(expr.getNumComponents() == 1);
+ const component = expr.getComponent(0);
+ if (component.getKind() == .Field) {
+ const field_decl = component.getField();
+ if (field_decl.getParent()) |record_decl| {
+ if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |type_name| {
+ const type_node = try Tag.type.create(c.arena, type_name);
+
+ var raw_field_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin());
+ const quoted_field_name = try std.fmt.allocPrint(c.arena, "\"{s}\"", .{raw_field_name});
+ const field_name_node = try Tag.string_literal.create(c.arena, quoted_field_name);
+
+ return Tag.byte_offset_of.create(c.arena, .{
+ .lhs = type_node,
+ .rhs = field_name_node,
+ });
+ }
+ }
+ }
+ return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "Failed to translate simple OffsetOfExpr", .{});
+}
+
+fn transOffsetOfExpr(
+ c: *Context,
+ scope: *Scope,
+ expr: *const clang.OffsetOfExpr,
+ result_used: ResultUsed,
+) TransError!Node {
+ if (expr.getNumComponents() == 1) {
+ const offsetof_expr = try transSimpleOffsetOfExpr(c, scope, expr);
+ return maybeSuppressResult(c, scope, result_used, offsetof_expr);
+ }
+
+ // TODO implement OffsetOfExpr with more than 1 component
+ // OffsetOfExpr API:
+ // call expr.getComponent(idx) while idx < expr.getNumComponents()
+ // component.getKind() will be either .Array or .Field (other kinds are C++-only)
+ // if .Field, use component.getField() to retrieve *clang.FieldDecl
+ // if .Array, use component.getArrayExprIndex() to get a c_uint which
+ // can be passed to expr.getIndexExpr(expr_index) to get the *clang.Expr for the array index
+
+ return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO: implement complex OffsetOfExpr translation", .{});
+}
+
fn transBinaryOperator(
c: *Context,
scope: *Scope,
src/zig_clang.cpp
@@ -2609,6 +2609,46 @@ const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct
return reinterpret_cast<const struct ZigClangExpr *>(casted->getUnderlyingExpr());
}
+enum ZigClangOffsetOfNode_Kind ZigClangOffsetOfNode_getKind(const struct ZigClangOffsetOfNode *self) {
+ auto casted = reinterpret_cast<const clang::OffsetOfNode *>(self);
+ return (ZigClangOffsetOfNode_Kind)casted->getKind();
+}
+
+unsigned ZigClangOffsetOfNode_getArrayExprIndex(const struct ZigClangOffsetOfNode *self) {
+ auto casted = reinterpret_cast<const clang::OffsetOfNode *>(self);
+ return casted->getArrayExprIndex();
+}
+
+struct ZigClangFieldDecl *ZigClangOffsetOfNode_getField(const struct ZigClangOffsetOfNode *self) {
+ auto casted = reinterpret_cast<const clang::OffsetOfNode *>(self);
+ return reinterpret_cast<ZigClangFieldDecl *>(casted->getField());
+}
+
+unsigned ZigClangOffsetOfExpr_getNumComponents(const struct ZigClangOffsetOfExpr *self) {
+ auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self);
+ return casted->getNumComponents();
+}
+
+unsigned ZigClangOffsetOfExpr_getNumExpressions(const struct ZigClangOffsetOfExpr *self) {
+ auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self);
+ return casted->getNumExpressions();
+}
+
+const struct ZigClangExpr *ZigClangOffsetOfExpr_getIndexExpr(const struct ZigClangOffsetOfExpr *self, unsigned idx) {
+ auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self);
+ return reinterpret_cast<const struct ZigClangExpr *>(casted->getIndexExpr(idx));
+}
+
+const struct ZigClangOffsetOfNode *ZigClangOffsetOfExpr_getComponent(const struct ZigClangOffsetOfExpr *self, unsigned idx) {
+ auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self);
+ return reinterpret_cast<const struct ZigClangOffsetOfNode *>(&casted->getComponent(idx));
+}
+
+ZigClangSourceLocation ZigClangOffsetOfExpr_getBeginLoc(const ZigClangOffsetOfExpr *self) {
+ auto casted = reinterpret_cast<const clang::OffsetOfExpr *>(self);
+ return bitcast(casted->getBeginLoc());
+}
+
struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
return bitcast(casted->getNamedType());
@@ -3008,6 +3048,11 @@ ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldD
return bitcast(casted->getLocation());
}
+const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const struct ZigClangFieldDecl *self) {
+ auto casted = reinterpret_cast<const clang::FieldDecl *>(self);
+ return reinterpret_cast<const ZigClangRecordDecl *>(casted->getParent());
+}
+
ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *self) {
auto casted = reinterpret_cast<const clang::FieldDecl *>(self);
return bitcast(casted->getType());
src/zig_clang.h
@@ -928,6 +928,13 @@ enum ZigClangUnaryExprOrTypeTrait_Kind {
ZigClangUnaryExprOrTypeTrait_KindPreferredAlignOf,
};
+enum ZigClangOffsetOfNode_Kind {
+ ZigClangOffsetOfNode_KindArray,
+ ZigClangOffsetOfNode_KindField,
+ ZigClangOffsetOfNode_KindIdentifier,
+ ZigClangOffsetOfNode_KindBase,
+};
+
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
struct ZigClangSourceLocation Loc);
ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
@@ -1161,6 +1168,16 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *);
+ZIG_EXTERN_C enum ZigClangOffsetOfNode_Kind ZigClangOffsetOfNode_getKind(const struct ZigClangOffsetOfNode *);
+ZIG_EXTERN_C unsigned ZigClangOffsetOfNode_getArrayExprIndex(const struct ZigClangOffsetOfNode *);
+ZIG_EXTERN_C struct ZigClangFieldDecl * ZigClangOffsetOfNode_getField(const struct ZigClangOffsetOfNode *);
+
+ZIG_EXTERN_C unsigned ZigClangOffsetOfExpr_getNumComponents(const struct ZigClangOffsetOfExpr *);
+ZIG_EXTERN_C unsigned ZigClangOffsetOfExpr_getNumExpressions(const struct ZigClangOffsetOfExpr *);
+ZIG_EXTERN_C const struct ZigClangExpr *ZigClangOffsetOfExpr_getIndexExpr(const struct ZigClangOffsetOfExpr *, unsigned idx);
+ZIG_EXTERN_C const struct ZigClangOffsetOfNode *ZigClangOffsetOfExpr_getComponent(const struct ZigClangOffsetOfExpr *, unsigned idx);
+ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangOffsetOfExpr_getBeginLoc(const struct ZigClangOffsetOfExpr *);
+
ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);
ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *);
@@ -1261,6 +1278,7 @@ ZIG_EXTERN_C bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *)
ZIG_EXTERN_C bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *);
+ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const struct ZigClangFieldDecl *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *);
ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *);
test/run_translated_c.zig
@@ -1073,4 +1073,37 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("offsetof",
+ \\#include <stddef.h>
+ \\#include <stdlib.h>
+ \\#define container_of(ptr, type, member) ({ \
+ \\ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ \\ (type *)( (char *)__mptr - offsetof(type,member) );})
+ \\typedef struct {
+ \\ int i;
+ \\ struct { int x; char y; int z; } s;
+ \\ float f;
+ \\} container;
+ \\int main(void) {
+ \\ if (offsetof(container, i) != 0) abort();
+ \\ if (offsetof(container, s) <= offsetof(container, i)) abort();
+ \\ if (offsetof(container, f) <= offsetof(container, s)) abort();
+ \\
+ \\ container my_container;
+ \\ typeof(my_container.s) *inner_member_pointer = &my_container.s;
+ \\ float *float_member_pointer = &my_container.f;
+ \\ int *anon_member_pointer = &my_container.s.z;
+ \\ container *my_container_p;
+ \\
+ \\ my_container_p = container_of(inner_member_pointer, container, s);
+ \\ if (my_container_p != &my_container) abort();
+ \\
+ \\ my_container_p = container_of(float_member_pointer, container, f);
+ \\ if (my_container_p != &my_container) abort();
+ \\
+ \\ if (container_of(anon_member_pointer, typeof(my_container.s), z) != inner_member_pointer) abort();
+ \\ return 0;
+ \\}
+ , "");
}