Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle opaque types #94

Merged
merged 5 commits into from
Jul 4, 2018
Merged

Handle opaque types #94

merged 5 commits into from
Jul 4, 2018

Conversation

kornilova203
Copy link
Member

@kornilova203 kornilova203 commented Jul 2, 2018

Closes #78
Closes #88

Create TypeDef instance that references OpaqueType
Replace OpaqueType instances by Struct or Union when types are declared

@kornilova203 kornilova203 force-pushed the opaque-type branch 3 times, most recently from 786e311 to 72d8aee Compare July 2, 2018 13:30
@kornilova203 kornilova203 changed the title Handle opaque types [WIP] Handle opaque types Jul 2, 2018
@kornilova203
Copy link
Member Author

OpaqueType was redundant.
For opaque types I decided to create instances of TypeDef that contain nullptr which is further replaced by a reference to Struct or Union.

@kornilova203 kornilova203 changed the title [WIP] Handle opaque types Handle opaque types Jul 3, 2018
@kornilova203 kornilova203 requested a review from jonas July 3, 2018 09:47
@@ -138,6 +147,10 @@ std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
std::make_shared<PrimitiveType>("Byte"), sizeInBits / 8);
}

if (tpe->isFunctionType()) {
return nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for static inline functions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it always used to return nullptr for function type, I just made it explicit.

I found this declaration in libio.h:

typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes);

That caused an error because TypeDef was created with nullptr.

Actually I am not aware of where function types may be used and what should we do with them. Maybe we should create an issue for investigating it.

@@ -317,7 +335,6 @@ T IR::getDeclarationWithName(std::vector<T> &declarations,
return declaration;
}
}
llvm::errs() << "Failed to get declaration for " << name << "\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we throw an exception here to avoid segfaults.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, nullptr is returned when:

  1. struct or union type is needed by a function (or other declaration) but the type is not declared yet. So TypeDef with nullptr will be created.
  2. When TreeVisitor visits struct/union declaration we need to check whether a TypeDef already exists for it.

I'll add comments about this to the code.

std::make_shared<Union>(std::move(name), std::move(fields), maxSize);
unions.push_back(u);
typeDef.get()->setType(u);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to unify addUnion and have it look up and conditional add/update the typedef. The same for addStruct.

bindgen/ir/IR.h Outdated
@@ -36,12 +37,24 @@ class IR {
std::shared_ptr<Type>
addStruct(std::string name, std::vector<Field *> fields, uint64_t typeSize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it explicit that it returns a TypeDef.

@@ -2,9 +2,15 @@
#include "../Utils.h"

TypeDef::TypeDef(std::string name, std::shared_ptr<Type> type)
: TypeAndName(std::move(name), type) {}
: TypeAndName(std::move(name), std::move(type)) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is std:: move needed here? My understanding is that ownership does not have to be explicitly transferred or is this an optimization?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, just a small optimization.

@@ -7,7 +7,7 @@ class ArrayType : public Type {
public:
ArrayType(std::shared_ptr<Type> elementsType, uint64_t size);

~ArrayType() override;
~ArrayType() override = default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL

@@ -115,7 +117,16 @@ void TreeVisitor::handleUnion(clang::RecordDecl *record, std::string name) {
fields.push_back(new Field(fname, ftype));
}

std::shared_ptr<Type> alias = ir.addUnion(name, std::move(fields), maxSize);
std::shared_ptr<Type> alias = nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to assign a default value

struct point *move(struct point *point, int x, int y);

typedef struct points points;
typedef union u u;
Copy link
Member

@jonas jonas Jul 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about declaring u before points before point and have u use points which uses point? It would test that we generate types in the right order.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will generate types in the order they appear in a header file.
It might be not a trivial task to sort them.

So in this example:

typedef struct points points;
typedef struct point point;

struct points {
    point *point1;
    point *point2;
};

struct point {
    int x;
    int y;
};

points appear before point. To sort them we need to find out that points actually uses point.
As I see it now we need to check for each type if it uses each other type and then do topological sort.
Tricky part is that there might be cyclic dependenceы:

struct b;
struct c;

struct a {
   struct b *b;
};

struct b {
    struct c *c;
};

struct c {
    struct a *a;
};

I will create an issue about it

@kornilova203 kornilova203 requested a review from jonas July 4, 2018 05:29
@kornilova203 kornilova203 removed the request for review from jonas July 4, 2018 18:39
@kornilova203 kornilova203 merged commit 753a512 into master Jul 4, 2018
@kornilova203 kornilova203 deleted the opaque-type branch July 4, 2018 18:48
@jonas
Copy link
Member

jonas commented Jul 4, 2018

Thanks for fixing the broken merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants