Skip to content

Commit ecc5aa2

Browse files
committed
Represent bit fields as arrays
1 parent 535b724 commit ecc5aa2

File tree

5 files changed

+43
-18
lines changed

5 files changed

+43
-18
lines changed

bindgen/ir/Struct.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
Field::Field(std::string name, std::shared_ptr<Type> type)
99
: TypeAndName(std::move(name), std::move(type)) {}
1010

11-
Field::Field(std::string name, std::shared_ptr<Type> type, uint64_t offset)
12-
: TypeAndName(std::move(name), std::move(type)), offset(offset) {}
11+
Field::Field(std::string name, std::shared_ptr<Type> type,
12+
uint64_t offsetInBits)
13+
: TypeAndName(std::move(name), std::move(type)),
14+
offsetInBits(offsetInBits) {}
1315

14-
uint64_t Field::getOffset() const { return offset; }
16+
uint64_t Field::getOffsetInBits() const { return offsetInBits; }
1517

1618
StructOrUnion::StructOrUnion(std::string name,
1719
std::vector<std::shared_ptr<Field>> fields,
@@ -34,7 +36,7 @@ Struct::Struct(std::string name, std::vector<std::shared_ptr<Field>> fields,
3436
typeSize(typeSize), isPacked(isPacked) {}
3537

3638
std::shared_ptr<TypeDef> Struct::generateTypeDef() {
37-
if (fields.size() < SCALA_NATIVE_MAX_STRUCT_FIELDS) {
39+
if (isRepresentedAsStruct()) {
3840
return std::make_shared<TypeDef>(getTypeAlias(), shared_from_this(),
3941
nullptr);
4042
} else {
@@ -56,7 +58,7 @@ std::string Struct::generateHelperClass() const {
5658
s << " implicit class " << type << "_ops(val p: native.Ptr[" << type
5759
<< "])"
5860
<< " extends AnyVal {\n";
59-
if (fields.size() <= SCALA_NATIVE_MAX_STRUCT_FIELDS) {
61+
if (isRepresentedAsStruct()) {
6062
s << generateHelperClassMethodsForStructRepresentation();
6163
} else {
6264
s << generateHelperClassMethodsForArrayRepresentation();
@@ -72,6 +74,9 @@ std::string Struct::generateHelperClass() const {
7274
}
7375

7476
bool Struct::hasHelperMethods() const {
77+
if (isBitField()) {
78+
return false;
79+
}
7580
if (!isRepresentedAsStruct()) {
7681
return !fields.empty();
7782
}
@@ -176,7 +181,7 @@ Struct::generateGetterForStructRepresentation(unsigned fieldIndex) const {
176181
}
177182

178183
bool Struct::isRepresentedAsStruct() const {
179-
return fields.size() <= SCALA_NATIVE_MAX_STRUCT_FIELDS;
184+
return fields.size() <= SCALA_NATIVE_MAX_STRUCT_FIELDS && !isBitField();
180185
}
181186

182187
std::string
@@ -188,9 +193,10 @@ Struct::generateSetterForArrayRepresentation(unsigned int fieldIndex) const {
188193
std::string castedField = "p._1";
189194

190195
PointerType pointerToFieldType = PointerType(field->getType());
191-
if (field->getOffset() > 0) {
192-
castedField = "(" + castedField + " + " +
193-
std::to_string(field->getOffset()) + ")";
196+
uint64_t offsetInBytes = field->getOffsetInBits() / 8;
197+
if (offsetInBytes > 0) {
198+
castedField =
199+
"(" + castedField + " + " + std::to_string(offsetInBytes) + ")";
194200
}
195201
castedField = "!" + castedField + ".cast[" + pointerToFieldType.str() + "]";
196202
if (isAliasForType<ArrayType>(field->getType().get()) ||
@@ -215,8 +221,9 @@ Struct::generateGetterForArrayRepresentation(unsigned fieldIndex) const {
215221
std::string methodBody;
216222

217223
PointerType pointerToFieldType = PointerType(field->getType());
218-
if (field->getOffset() > 0) {
219-
methodBody = "(p._1 + " + std::to_string(field->getOffset()) + ")";
224+
uint64_t offsetInBytes = field->getOffsetInBits() / 8;
225+
if (offsetInBytes > 0) {
226+
methodBody = "(p._1 + " + std::to_string(offsetInBytes) + ")";
220227
} else {
221228
methodBody = "p._1";
222229
}
@@ -233,7 +240,16 @@ Struct::generateGetterForArrayRepresentation(unsigned fieldIndex) const {
233240
s << " def " << getter << ": " << returnType << " = " << methodBody
234241
<< "\n";
235242
return s.str();
236-
return "";
243+
}
244+
245+
bool Struct::isBitField() const {
246+
// TODO: find proper way to check it
247+
for (const auto &field : fields) {
248+
if (field->getOffsetInBits() % 8 != 0) {
249+
return true;
250+
}
251+
}
252+
return false;
237253
}
238254

239255
Union::Union(std::string name, std::vector<std::shared_ptr<Field>> fields,

bindgen/ir/Struct.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ class Field : public TypeAndName {
1313
public:
1414
Field(std::string name, std::shared_ptr<Type> type);
1515

16-
Field(std::string name, std::shared_ptr<Type> type, uint64_t offset);
16+
Field(std::string name, std::shared_ptr<Type> type, uint64_t offsetInBits);
1717

18-
uint64_t getOffset() const;
18+
uint64_t getOffsetInBits() const;
1919

2020
protected:
2121
/**
2222
* Offset in bytes from address of struct/union.
2323
*/
24-
uint64_t offset = 0;
24+
uint64_t offsetInBits = 0;
2525
};
2626

2727
class StructOrUnion {
@@ -99,6 +99,8 @@ class Struct : public StructOrUnion,
9999
std::string generateSetterForArrayRepresentation(unsigned fieldIndex) const;
100100

101101
std::string generateGetterForArrayRepresentation(unsigned fieldIndex) const;
102+
103+
bool isBitField() const;
102104
};
103105

104106
class Union : public StructOrUnion,

bindgen/visitor/TreeVisitor.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,8 @@ void TreeVisitor::handleStruct(clang::RecordDecl *record, std::string name) {
135135
typeTranslator.translate(field->getType(), &name);
136136
uint64_t recordOffsetInBits =
137137
recordLayout.getFieldOffset(field->getFieldIndex());
138-
assert(recordOffsetInBits % 8 == 0);
139-
fields.push_back(std::make_shared<Field>(
140-
field->getNameAsString(), ftype, recordOffsetInBits / 8));
138+
fields.push_back(std::make_shared<Field>(field->getNameAsString(),
139+
ftype, recordOffsetInBits));
141140

142141
cycleDetection.AddDependency(newName, field->getType());
143142
}

tests/samples/Struct.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ struct __attribute__((__packed__)) packedStruct { // no helper methods
6060
char a;
6161
};
6262

63+
struct bitFieldStruct { // no helper methods
64+
unsigned char b1 : 3;
65+
unsigned char : 0; // start a new byte
66+
unsigned char b2 : 6;
67+
unsigned char b3 : 2;
68+
};
69+
6370
char getCharFromAnonymousStruct(struct structWithAnonymousStruct *s);
6471

6572
char getIntFromAnonymousStruct(struct structWithAnonymousStruct *s);

tests/samples/Struct.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ object Struct {
1414
type struct_bigStruct = native.CArray[Byte, native.Nat.Digit[native.Nat._1, native.Nat.Digit[native.Nat._1, native.Nat._2]]]
1515
type struct_structWithAnonymousStruct = native.CStruct2[native.CInt, native.CArray[Byte, native.Nat._8]]
1616
type struct_packedStruct = native.CStruct1[native.CChar]
17+
type struct_bitFieldStruct = native.CArray[Byte, native.Nat._2]
1718
type enum_struct_op = native.CUnsignedInt
1819
def setPoints(points: native.Ptr[struct_points], x1: native.CInt, y1: native.CInt, x2: native.CInt, y2: native.CInt): Unit = native.extern
1920
def getPoint(points: native.Ptr[struct_points], pointIndex: enum_pointIndex): native.CInt = native.extern

0 commit comments

Comments
 (0)