-
Notifications
You must be signed in to change notification settings - Fork 7
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
Changes from all commits
40a4d0e
494e4d9
8db4611
4d5fe4b
5ae0664
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
#include "TypeTranslator.h" | ||
#include "Utils.h" | ||
#include "ir/types/FunctionPointerType.h" | ||
#include "ir/types/PointerType.h" | ||
|
||
TypeTranslator::TypeTranslator(clang::ASTContext *ctx_) : ctx(ctx_), typeMap() { | ||
TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir) | ||
: ctx(ctx_), ir(ir), typeMap() { | ||
|
||
// Native Types | ||
typeMap["void"] = "Unit"; | ||
|
@@ -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]"; | ||
} | ||
|
||
std::string | ||
TypeTranslator::TranslateFunctionPointer(const clang::QualType &qtpe, | ||
const std::string *avoid) { | ||
const clang::PointerType *ptr = | ||
qtpe.getTypePtr()->getAs<clang::PointerType>(); | ||
Type *TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe, | ||
const std::string *avoid) { | ||
const auto *ptr = qtpe.getTypePtr()->getAs<clang::PointerType>(); | ||
const clang::QualType &inner = ptr->getPointeeType(); | ||
|
||
if (inner->isFunctionProtoType()) { | ||
const clang::FunctionProtoType *fc = | ||
inner->getAs<clang::FunctionProtoType>(); | ||
std::string ret = Translate(fc->getReturnType(), avoid); | ||
std::string params = ""; | ||
int counter = 0; | ||
const auto *fc = inner->getAs<clang::FunctionProtoType>(); | ||
Type *returnType = translate(fc->getReturnType(), avoid); | ||
std::vector<Type *> parametersTypes; | ||
|
||
for (const clang::QualType ¶m : fc->param_types()) { | ||
params += Translate(param, avoid); | ||
params += ", "; | ||
counter++; | ||
parametersTypes.push_back(translate(param, avoid)); | ||
} | ||
|
||
std::string variad = ""; | ||
|
||
if (fc->isVariadic()) { | ||
counter++; | ||
variad = "native.CVararg, "; | ||
} | ||
|
||
return std::string("native.CFunctionPtr") + std::to_string(counter) + | ||
"[" + params + variad + ret + "]"; | ||
return new FunctionPointerType(returnType, parametersTypes, | ||
fc->isVariadic()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❤️ |
||
|
||
} else { | ||
llvm::errs() << "Unsupported function pointer type: " | ||
|
@@ -68,111 +57,111 @@ TypeTranslator::TranslateFunctionPointer(const clang::QualType &qtpe, | |
} | ||
} | ||
|
||
std::string TypeTranslator::TranslatePointer(const clang::QualType &pte, | ||
const std::string *avoid) { | ||
Type *TypeTranslator::translatePointer(const clang::QualType &pte, | ||
const std::string *avoid) { | ||
|
||
if (pte->isBuiltinType()) { | ||
const clang::BuiltinType *as = pte->getAs<clang::BuiltinType>(); | ||
|
||
// Take care of void* | ||
if (as->getKind() == clang::BuiltinType::Void) { | ||
return "native.Ptr[Byte]"; | ||
return new PointerType(new PrimitiveType("Byte")); | ||
} | ||
|
||
// Take care of char* | ||
if (as->getKind() == clang::BuiltinType::Char_S || | ||
as->getKind() == clang::BuiltinType::SChar) { | ||
return "native.CString"; | ||
// TODO: new PointerType(new PrimitiveType("native.CChar")) | ||
return new PrimitiveType("native.CString"); | ||
} | ||
} | ||
|
||
return std::string("native.Ptr[") + Translate(pte, avoid) + | ||
std::string("]"); | ||
return new PointerType(translate(pte, avoid)); | ||
} | ||
|
||
std::string | ||
TypeTranslator::TranslateStructOrUnion(const clang::QualType &qtpe) { | ||
if (qtpe->hasUnnamedOrLocalType()) { | ||
// TODO: Verify that the local part is not a problem | ||
uint64_t size = ctx->getTypeSize(qtpe); | ||
return "native.CArray[Byte, " + uint64ToScalaNat(size) + "]"; | ||
} | ||
|
||
Type * | ||
TypeTranslator::translateStructOrUnionOrEnum(const clang::QualType &qtpe) { | ||
std::string name = qtpe.getUnqualifiedType().getAsString(); | ||
|
||
// TODO: do it properly | ||
size_t f = name.find(std::string("struct __dirstream")); | ||
if (f != std::string::npos) { | ||
return std::string("native.CArray[Byte, Digit[_3, Digit[_2, _0]]]"); | ||
} | ||
|
||
f = name.find(" "); | ||
if (f != std::string::npos) { | ||
return name.replace(f, std::string(" ").length(), "_"); | ||
auto it = aliasesMap.find(name); | ||
if (it != aliasesMap.end()) { | ||
/* name contains space: struct <name>. | ||
* Use type alias instead struct type */ | ||
return (*it).second; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand this branch. This is when we reference a previously declared There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider following example: struct myStruct {
int a;
}; Generated Scala code for the struct: type struct_myStruct = native.CStruct1[native.CInt] Then we find the function that uses out struct: void myFunction(struct myStruct, s);
So we will reference a |
||
} | ||
return name; | ||
/* type has typedef alias */ | ||
return ir.getTypeDefWithName(name); | ||
} | ||
|
||
std::string TypeTranslator::TranslateEnum(const clang::QualType &qtpe) { | ||
std::string name = qtpe.getUnqualifiedType().getAsString(); | ||
size_t f = name.find(" "); | ||
if (f != std::string::npos) { | ||
return name.replace(f, std::string(" ").length(), "_"); | ||
Type *TypeTranslator::translateStructOrUnion(const clang::QualType &qtpe) { | ||
if (qtpe->hasUnnamedOrLocalType()) { | ||
// TODO: Verify that the local part is not a problem | ||
uint64_t size = ctx->getTypeSize(qtpe); | ||
return new ArrayType(new PrimitiveType("Byte"), size); | ||
} | ||
return name; | ||
|
||
return translateStructOrUnionOrEnum(qtpe); | ||
} | ||
|
||
std::string | ||
TypeTranslator::TranslateConstantArray(const clang::ConstantArrayType *ar, | ||
const std::string *avoid) { | ||
Type *TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar, | ||
const std::string *avoid) { | ||
const uint64_t size = ar->getSize().getZExtValue(); | ||
const std::string nat = uint64ToScalaNat(size); | ||
return "native.CArray[" + Translate(ar->getElementType(), avoid) + ", " + | ||
nat + "]"; | ||
return new ArrayType(translate(ar->getElementType(), avoid), size); | ||
} | ||
|
||
std::string TypeTranslator::Translate(const clang::QualType &qtpe, | ||
const std::string *avoid) { | ||
Type *TypeTranslator::translate(const clang::QualType &qtpe, | ||
const std::string *avoid) { | ||
|
||
const clang::Type *tpe = qtpe.getTypePtr(); | ||
|
||
if (typeEquals(tpe, avoid)) { | ||
// This is a type that we want to avoid the usage. | ||
//Êxample: A struct that has a pointer to itself | ||
// Êxample: A struct that has a pointer to itself | ||
uint64_t size = ctx->getTypeSize(tpe); | ||
return "native.CArray[Byte, " + uint64ToScalaNat(size) + "]"; | ||
return new ArrayType(new PrimitiveType("Byte"), size); | ||
} | ||
|
||
if (tpe->isFunctionPointerType()) { | ||
return TranslateFunctionPointer(qtpe, avoid); | ||
return translateFunctionPointer(qtpe, avoid); | ||
|
||
} else if (tpe->isPointerType()) { | ||
return TranslatePointer( | ||
return translatePointer( | ||
tpe->getAs<clang::PointerType>()->getPointeeType(), avoid); | ||
|
||
} else if (qtpe->isStructureType() || qtpe->isUnionType()) { | ||
return handleReservedWords(TranslateStructOrUnion(qtpe)); | ||
} else if (qtpe->isStructureType()) { | ||
return translateStructOrUnion(qtpe); | ||
|
||
} else if (qtpe->isUnionType()) { | ||
return translateStructOrUnion(qtpe); | ||
|
||
} else if (qtpe->isEnumeralType()) { | ||
return TranslateEnum(qtpe); | ||
return translateStructOrUnionOrEnum(qtpe); | ||
|
||
} else if (qtpe->isConstantArrayType()) { | ||
return TranslateConstantArray(ctx->getAsConstantArrayType(qtpe), avoid); | ||
return translateConstantArray(ctx->getAsConstantArrayType(qtpe), avoid); | ||
} else if (qtpe->isArrayType()) { | ||
return TranslatePointer(ctx->getAsArrayType(qtpe)->getElementType(), | ||
return translatePointer(ctx->getAsArrayType(qtpe)->getElementType(), | ||
avoid); | ||
} else { | ||
|
||
auto found = typeMap.find(qtpe.getUnqualifiedType().getAsString()); | ||
if (found != typeMap.end()) { | ||
return handleReservedWords(found->second); | ||
return new PrimitiveType(found->second); | ||
} else { | ||
// TODO: Properly handle non-default types | ||
return handleReservedWords(qtpe.getUnqualifiedType().getAsString()); | ||
return ir.getTypeDefWithName( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, because |
||
qtpe.getUnqualifiedType().getAsString()); | ||
} | ||
} | ||
} | ||
|
||
void TypeTranslator::AddTranslation(std::string from, std::string to) { | ||
typeMap[from] = to; | ||
void TypeTranslator::addAlias(std::string cName, Type *type) { | ||
aliasesMap[cName] = type; | ||
} | ||
|
||
std::string TypeTranslator::getTypeFromTypeMap(std::string cType) { | ||
auto it = typeMap.find(cType); | ||
if (it != typeMap.end()) { | ||
return (*it).second; | ||
} | ||
return ""; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,11 @@ | ||
#pragma once | ||
|
||
#include <clang/AST/AST.h> | ||
#include <clang/AST/ASTContext.h> | ||
#include "ir/IR.h" | ||
#include <clang/Tooling/Tooling.h> | ||
|
||
class TypeTranslator { | ||
private: | ||
clang::ASTContext *ctx; | ||
std::map<std::string, std::string> typeMap; | ||
|
||
public: | ||
explicit TypeTranslator(clang::ASTContext *ctx); | ||
void AddTranslation(std::string from, std::string to); | ||
TypeTranslator(clang::ASTContext *ctx, IR &ir); | ||
|
||
/** | ||
* @brief Translate the qualified type from c to a scala type | ||
|
@@ -20,14 +14,36 @@ class TypeTranslator { | |
* structs, unions, ... | ||
* @return the type translated | ||
*/ | ||
std::string Translate(const clang::QualType &tpe, | ||
const std::string * = nullptr); | ||
std::string TranslateFunctionPointer(const clang::QualType &qtpe, | ||
const std::string *avoid); | ||
std::string TranslatePointer(const clang::QualType &pointee, | ||
Type *translate(const clang::QualType &tpe, const std::string * = nullptr); | ||
|
||
void addAlias(std::string cName, Type *type); | ||
|
||
std::string getTypeFromTypeMap(std::string cType); | ||
|
||
private: | ||
clang::ASTContext *ctx; | ||
IR &ir; | ||
|
||
/** | ||
* Primitive types | ||
*/ | ||
std::map<std::string, std::string> typeMap; | ||
|
||
/** | ||
* Maps C struct, union or enum name to Type alias | ||
*/ | ||
std::map<std::string, Type *> aliasesMap; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I quite liked the unification in the original 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll create an issue for deallocation There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
|
||
Type *translateStructOrUnionOrEnum(const clang::QualType &qtpe); | ||
|
||
Type *translateStructOrUnion(const clang::QualType &qtpe); | ||
|
||
Type *translateFunctionPointer(const clang::QualType &qtpe, | ||
const std::string *avoid); | ||
|
||
Type *translatePointer(const clang::QualType &pointee, | ||
const std::string *avoid); | ||
|
||
Type *translateConstantArray(const clang::ConstantArrayType *ar, | ||
const std::string *avoid); | ||
std::string TranslateStructOrUnion(const clang::QualType &qtpe); | ||
std::string TranslateEnum(const clang::QualType &qtpe); | ||
std::string TranslateConstantArray(const clang::ConstantArrayType *ar, | ||
const std::string *avoid); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍