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

Store types in ir #68

Merged
merged 5 commits into from
Jun 28, 2018
Merged

Store types in ir #68

merged 5 commits into from
Jun 28, 2018

Conversation

kornilova203
Copy link
Member

Closes #52

Added multiple new classes in ir/types directory. I decided not to wrap struct/union/enum into a Type class instance but inherit the classes from Type.

One of changes:
Typedefs for struct/union/enum are generated right after a declaration was visited.
Example of such typedef:

type struct_point = native.CStruct2[native.CInt, native.CInt]

Created typedef points to struct/union/enum instance and it is added to translation map, so all other declarations that use type of this struct/union/enum will point to the created typedef.

I will carefully review the code later.

type struct_point = native.CStruct2[native.CInt, native.CInt]
type point_s = native.Ptr[struct_point]
Copy link
Member

Choose a reason for hiding this comment

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

👍

type toggle_e = enum_toggle_e
type int2int = native.CFunctionPtr1[native.CInt, native.CInt]
type day2string = native.CFunctionPtr1[enum_days, native.CString]
type toggle = native.CFunctionPtr1[toggle_e, Unit]
type enum_days = native.CUnsignedInt
type enum_toggle_e = native.CUnsignedInt
Copy link
Member

Choose a reason for hiding this comment

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

It looks like you are doing a lot of refactoring. Would you mind to split out things like reordering of the generated code to a separate PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

Generated code is reordered because typedefs are now generated earlier. Order of types happens to be more logical but it is not a separate refactoring

/**
* For example native.CInt
*/
class SimpleType : public Type {
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 name it PrimitiveType.

Copy link
Member Author

Choose a reason for hiding this comment

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

Name is good

@kornilova203
Copy link
Member Author

I tried to do memory management properly but got a problem:
Type instances are stored in other types and in such objects as Field. They can be deleted if they are not contained in IR (struct, union, enum or typedef). But the problem is that vector<Field> may copy-construct Fields and delete them that triggers destructor of Type.

It is not possible to use Type values instead of pointers because inheritance will not work properly. Using vectors of pointers for everything (so destructors are not called by vector) also does not seem to be a good idea.

I decided to not spend too much time on it and leave it as it is.

@kornilova203 kornilova203 changed the title [WIP] Store types in ir Store types in ir Jun 25, 2018
@jonas
Copy link
Member

jonas commented Jun 25, 2018

Okay, maybe we should create a ticket to investigate sometime in the future. I will take a second look when #62 has been merged and the conflict in this PR has been fixed.

@kornilova203 kornilova203 requested a review from jonas June 27, 2018 06:44
Copy link
Member

@jonas jonas left a comment

Choose a reason for hiding this comment

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

Make a second pass. Impressive work.

std::string qtpeString = tpeTransl.Translate(qtpe);
Type *type = tpeTransl.translate(qtpe);
if (type == nullptr) {
/* temp fix for function pointer */
Copy link
Member

Choose a reason for hiding this comment

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

What temporary fix?

Copy link
Member Author

Choose a reason for hiding this comment

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

The function recursively extracts pointee type from pointer type to add a dependency.
So it extracts FunctionType from FunctionPointerType but TypeTranslator is unable to translate FunctionType
I'll make the comment more clear

@@ -27,38 +30,24 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_) : ctx(ctx_), typeMap() {
typeMap["char32_t"] = "native.CChar32";
typeMap["float"] = "native.CFloat";
typeMap["double"] = "native.CDouble";
typeMap["void*"] = "native.Ptr[Byte]";
Copy link
Member

Choose a reason for hiding this comment

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

👍

return std::string("native.CFunctionPtr") + std::to_string(counter) +
"[" + params + variad + ret + "]";
return new FunctionPointerType(returnType, parametersTypes,
fc->isVariadic());
Copy link
Member

Choose a reason for hiding this comment

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

❤️

ir.addEnum(name, typeTranslator.Translate(enumdecl->getIntegerType()),
enumerators);
std::string scalaType = typeTranslator.getTypeFromTypeMap(
enumdecl->getIntegerType().getUnqualifiedType().getAsString());
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to get rid of this string translation.

}

// Take care of char*
if (as->getKind() == clang::BuiltinType::Char_S ||
as->getKind() == clang::BuiltinType::SChar) {
return "native.CString";
return new PrimitiveType("native.CString");
Copy link
Member

Choose a reason for hiding this comment

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

Could this be a constant? Similar for the other "native.$type".

Also CString is technically char * so more logically would be encoded as new PointerType(new PrimitiveType("native.CChar")). Would you mind leaving a FIXME or comment related to this?

Copy link
Member Author

Choose a reason for hiding this comment

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

sure

std::string
TypeTranslator::TranslateConstantArray(const clang::ConstantArrayType *ar,
const std::string *avoid) {
Type *TypeTranslator::translateEnum(const clang::QualType &qtpe) {
Copy link
Member

Choose a reason for hiding this comment

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

It looks like this method is reused actually be used by translateStruct or even merged with it once the union specific if branch is removed.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍

} else {
// TODO: Properly handle non-default types
return handleReservedWords(qtpe.getUnqualifiedType().getAsString());
return ir.getTypeDefWithName(
Copy link
Member

Choose a reason for hiding this comment

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

I guess here we don't want to go through the alias map?

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, because struct myStruct will be translated above (the same for enum and union)

/**
* Maps C struct, union or enum name to Type alias
*/
std::map<std::string, Type *> aliasesMap;
Copy link
Member

Choose a reason for hiding this comment

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

I quite liked the unification in the original typeMap. Would it make sense to change it to be defined as:

std::map<std::string, Type *> typeMap

populated with

     typeMap["void"] = new PrimitiveType("Unit");
     typeMap["bool"] = new PrimitiveType("native.CBool");
     typeMap["_Bool"] = new PrimitiveType("native.CBool");
     // ...

I assume the problem is with the deallocation?

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, deallocation is the problem (well, these instances are not deallocated now, but changing type of the map will make fixing it harder)

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll create an issue for deallocation

Copy link
Member Author

Choose a reason for hiding this comment

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

Or simply do it now, because I do not want the code that does not deallocate objects

@@ -109,60 +111,63 @@ void DefineFinder::addNumericConstantDefine(const std::string &macroName,
const clang::Token &token,
bool positive) {
clang::NumericLiteralParser parser(literal, token.getLocation(), pp);
std::string type;
Type *type = nullptr;
Copy link
Member

Choose a reason for hiding this comment

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

This method could be simpler by using std::string typeName and still use "native.CLongLong etc. and do the new PrimitiveType(typeName) allocation at the end.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍

#include "Type.h"
#include "../../Utils.h"

std::string Type::str() const { return handleReservedWords(_str()); }
Copy link
Member

Choose a reason for hiding this comment

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

Won't this call handleReservedWords() on stuff like native.CFunctionPtr[...]? It seems that it over-do it. How hard would it be to selectively call it for any type that returns a simple name and then get rid of _str()?

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 shouldn't be a problem

@kornilova203
Copy link
Member Author

Now all objects are deallocated. I checked it with Valgrind

@kornilova203
Copy link
Member Author

kornilova203 commented Jun 28, 2018

But it is a bit ugly because some types are shared between objects (Struct, Union, Enum and TypeDef) and other Types are stored in one object.
Now I think that it would be better not to inherit Struct (an other IR types) from Type but instead create wrappers of type Type so Type instances will not be created for each object and will not be shared. I hope it will make code less complicated

Copy link
Member

@jonas jonas left a comment

Choose a reason for hiding this comment

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

Stellar work!

@kornilova203 kornilova203 merged commit 4d30963 into master Jun 28, 2018
@kornilova203 kornilova203 deleted the store-types-in-ir branch June 28, 2018 14:43
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.

2 participants