Add `is_trivial_abi` bit to Record IR.
Without a way to look up the Record for a given CcType/RsType, there is no way to make this influence code generation of actual calls which use this type. So this is currently unused.
However, this may be enough, by itself, to mark a type as trivially relocatable. A type with this bit can be passed through registers, which means that, by definition, its memory location doesn't matter, and it can be trivially relocated.
For example, see this godbolt link showing that marking a class as trivial_abi breaks it by causing it to get relocated!
https://godbolt.org/z/voMa5TPKq
PiperOrigin-RevId: 400123681
diff --git a/rs_bindings_from_cc/ast_visitor.cc b/rs_bindings_from_cc/ast_visitor.cc
index 69fb3d2..bce7fd7 100644
--- a/rs_bindings_from_cc/ast_visitor.cc
+++ b/rs_bindings_from_cc/ast_visitor.cc
@@ -119,7 +119,8 @@
ir_.records.push_back({.identifier = GetTranslatedName(record_decl),
.fields = std::move(fields),
.size = layout.getSize().getQuantity(),
- .alignment = layout.getAlignment().getQuantity()});
+ .alignment = layout.getAlignment().getQuantity(),
+ .is_trivial_abi = record_decl->canPassInRegisters()});
return true;
}
diff --git a/rs_bindings_from_cc/ir.cc b/rs_bindings_from_cc/ir.cc
index 92c5f4f..16c1b0d 100644
--- a/rs_bindings_from_cc/ir.cc
+++ b/rs_bindings_from_cc/ir.cc
@@ -115,6 +115,7 @@
result["fields"] = std::move(json_fields);
result["size"] = size;
result["alignment"] = alignment;
+ result["is_trivial_abi"] = is_trivial_abi;
return result;
}
diff --git a/rs_bindings_from_cc/ir.h b/rs_bindings_from_cc/ir.h
index a670deb..bf94635 100644
--- a/rs_bindings_from_cc/ir.h
+++ b/rs_bindings_from_cc/ir.h
@@ -187,6 +187,16 @@
// Size and alignment in bytes.
int64_t size;
int64_t alignment;
+
+ // Whether this type is passed by value as if it were a trivial type (the same
+ // as it would be if it were a struct in C).
+ //
+ // This can be either due to language rules (it *is* a trivial type), or due
+ // to the usage of a Clang attribute that forces trivial for calls:
+ //
+ // * https://eel.is/c++draft/class.temporary#3
+ // * https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
+ bool is_trivial_abi = false;
};
// A complete intermediate representation of bindings for publicly accessible
diff --git a/rs_bindings_from_cc/ir.rs b/rs_bindings_from_cc/ir.rs
index 928d20d..62db183 100644
--- a/rs_bindings_from_cc/ir.rs
+++ b/rs_bindings_from_cc/ir.rs
@@ -79,6 +79,7 @@
pub fields: Vec<Field>,
pub size: usize,
pub alignment: usize,
+ pub is_trivial_abi: bool,
}
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Deserialize)]
@@ -204,7 +205,8 @@
}
],
"size": 12,
- "alignment": 4
+ "alignment": 4,
+ "is_trivial_abi": true
}
]
}
@@ -256,6 +258,7 @@
],
size: 12,
alignment: 4,
+ is_trivial_abi: true,
}],
..Default::default()
};
@@ -285,7 +288,8 @@
}
],
"size": 8,
- "alignment": 8
+ "alignment": 8,
+ "is_trivial_abi": true
}
]
}
@@ -319,6 +323,7 @@
}],
size: 8,
alignment: 8,
+ is_trivial_abi: true,
}],
..Default::default()
};
diff --git a/rs_bindings_from_cc/ir_test.cc b/rs_bindings_from_cc/ir_test.cc
index 025357f..49f4905 100644
--- a/rs_bindings_from_cc/ir_test.cc
+++ b/rs_bindings_from_cc/ir_test.cc
@@ -107,7 +107,8 @@
}
],
"size": 12,
- "alignment": 4
+ "alignment": 4,
+ "is_trivial_abi": true
}
]
})j");
@@ -137,7 +138,8 @@
.offset = 64},
},
.size = 12,
- .alignment = 4}}};
+ .alignment = 4,
+ .is_trivial_abi = true}}};
EXPECT_EQ(ir.ToJson(), expected);
}
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index 6267238..74b3e6b 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -516,6 +516,7 @@
],
size: 12,
alignment: 4,
+ is_trivial_abi: true,
}],
functions: vec![],
};