|
|
|
|
@@ -31,6 +31,30 @@ namespace header_checker {
|
|
|
|
|
namespace dumper {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// Helper Function
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static repr::AccessSpecifierIR AccessClangToIR(
|
|
|
|
|
const clang::AccessSpecifier sp) {
|
|
|
|
|
switch (sp) {
|
|
|
|
|
case clang::AS_private: {
|
|
|
|
|
return repr::AccessSpecifierIR::PrivateAccess;
|
|
|
|
|
}
|
|
|
|
|
case clang::AS_protected: {
|
|
|
|
|
return repr::AccessSpecifierIR::ProtectedAccess;
|
|
|
|
|
}
|
|
|
|
|
default: {
|
|
|
|
|
return repr::AccessSpecifierIR::PublicAccess;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// ABI Wrapper
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
ABIWrapper::ABIWrapper(
|
|
|
|
|
clang::MangleContext *mangle_contextp,
|
|
|
|
|
clang::ASTContext *ast_contextp,
|
|
|
|
|
@@ -43,6 +67,21 @@ ABIWrapper::ABIWrapper(
|
|
|
|
|
module_(module),
|
|
|
|
|
ast_caches_(ast_caches) {}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
|
|
|
|
|
const clang::CompilerInstance *cip) {
|
|
|
|
|
clang::SourceManager &sm = cip->getSourceManager();
|
|
|
|
|
clang::SourceLocation location = decl->getLocation();
|
|
|
|
|
// We need to use the expansion location to identify whether we should recurse
|
|
|
|
|
// into the AST Node or not. For eg: macros specifying LinkageSpecDecl can
|
|
|
|
|
// have their spelling location defined somewhere outside a source / header
|
|
|
|
|
// file belonging to a library. This should not allow the AST node to be
|
|
|
|
|
// skipped. Its expansion location will still be the source-file / header
|
|
|
|
|
// belonging to the library.
|
|
|
|
|
clang::SourceLocation expansion_location = sm.getExpansionLoc(location);
|
|
|
|
|
llvm::StringRef file_name = sm.getFilename(expansion_location);
|
|
|
|
|
return utils::RealPath(file_name.str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetCachedDeclSourceFile(
|
|
|
|
|
const clang::Decl *decl, const clang::CompilerInstance *cip) {
|
|
|
|
|
assert(decl != nullptr);
|
|
|
|
|
@@ -53,6 +92,53 @@ std::string ABIWrapper::GetCachedDeclSourceFile(
|
|
|
|
|
return result->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetMangledNameDecl(
|
|
|
|
|
const clang::NamedDecl *decl, clang::MangleContext *mangle_contextp) {
|
|
|
|
|
if (!mangle_contextp->shouldMangleDeclName(decl)) {
|
|
|
|
|
clang::IdentifierInfo *identifier = decl->getIdentifier();
|
|
|
|
|
return identifier ? identifier->getName() : "";
|
|
|
|
|
}
|
|
|
|
|
std::string mangled_name;
|
|
|
|
|
llvm::raw_string_ostream ostream(mangled_name);
|
|
|
|
|
mangle_contextp->mangleName(decl, ostream);
|
|
|
|
|
ostream.flush();
|
|
|
|
|
return mangled_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::SetupTemplateArguments(const clang::TemplateArgumentList *tl,
|
|
|
|
|
repr::TemplatedArtifactIR *ta,
|
|
|
|
|
const std::string &source_file) {
|
|
|
|
|
repr::TemplateInfoIR template_info;
|
|
|
|
|
for (int i = 0; i < tl->size(); i++) {
|
|
|
|
|
const clang::TemplateArgument &arg = (*tl)[i];
|
|
|
|
|
// TODO: More comprehensive checking needed.
|
|
|
|
|
if (arg.getKind() != clang::TemplateArgument::Type) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
clang::QualType type = arg.getAsType();
|
|
|
|
|
template_info.AddTemplateElement(
|
|
|
|
|
repr::TemplateElementIR(GetTypeId(type)));
|
|
|
|
|
if (!CreateBasicNamedAndTypedDecl(type, source_file)) {
|
|
|
|
|
llvm::errs() << "Setting up template arguments failed\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ta->SetTemplateInfo(std::move(template_info));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::SetupFunctionParameter(
|
|
|
|
|
repr::CFunctionLikeIR *functionp, const clang::QualType qual_type,
|
|
|
|
|
bool has_default_arg, const std::string &source_file, bool is_this_ptr) {
|
|
|
|
|
if (!CreateBasicNamedAndTypedDecl(qual_type, source_file)) {
|
|
|
|
|
llvm::errs() << "Setting up function parameter failed\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
functionp->AddParameter(repr::ParamIR(
|
|
|
|
|
GetTypeId(qual_type), has_default_arg, is_this_ptr));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const clang::TagDecl *GetTagDecl(clang::QualType qual_type) {
|
|
|
|
|
const clang::Type *type_ptr = qual_type.getCanonicalType().getTypePtr();
|
|
|
|
|
assert(type_ptr != nullptr);
|
|
|
|
|
@@ -105,81 +191,6 @@ static bool IsReferencingType(clang::QualType qual_type) {
|
|
|
|
|
return is_array || is_ptr || is_reference || qual_type.hasLocalQualifiers();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static clang::QualType GetReferencedType(const clang::QualType qual_type);
|
|
|
|
|
|
|
|
|
|
static clang::QualType GetFinalReferencedType(clang::QualType qual_type) {
|
|
|
|
|
while (IsReferencingType(qual_type)) {
|
|
|
|
|
qual_type = GetReferencedType(qual_type);
|
|
|
|
|
}
|
|
|
|
|
return qual_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::TypeNameWithFinalDestination(clang::QualType qual_type) {
|
|
|
|
|
clang::QualType canonical_qual_type = qual_type.getCanonicalType();
|
|
|
|
|
const std::string qual_type_name = QualTypeToString(canonical_qual_type);
|
|
|
|
|
clang::QualType final_destination_type =
|
|
|
|
|
GetFinalReferencedType(canonical_qual_type);
|
|
|
|
|
const clang::RecordDecl *anon_record =
|
|
|
|
|
GetAnonymousRecord(final_destination_type);
|
|
|
|
|
if (anon_record) {
|
|
|
|
|
clang::SourceManager &sm = cip_->getSourceManager();
|
|
|
|
|
clang::SourceLocation location = anon_record->getLocation();
|
|
|
|
|
return qual_type_name + " at " + location.printToString(sm);
|
|
|
|
|
}
|
|
|
|
|
return qual_type_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetKeyForTypeId(clang::QualType qual_type) {
|
|
|
|
|
clang::QualType canonical_qual_type = qual_type.getCanonicalType();
|
|
|
|
|
clang::QualType final_destination_type =
|
|
|
|
|
GetFinalReferencedType(canonical_qual_type);
|
|
|
|
|
// Get the tag id for final destionation and add that to the type name with
|
|
|
|
|
// final destination. This helps in avoiding aliasing of types when fully
|
|
|
|
|
// qualified type-name doesn't expand all template parameters with their
|
|
|
|
|
// namespaces.
|
|
|
|
|
return TypeNameWithFinalDestination(qual_type) +
|
|
|
|
|
GetTypeUniqueId(GetTagDecl(final_destination_type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
|
|
|
|
|
const clang::CompilerInstance *cip) {
|
|
|
|
|
clang::SourceManager &sm = cip->getSourceManager();
|
|
|
|
|
clang::SourceLocation location = decl->getLocation();
|
|
|
|
|
// We need to use the expansion location to identify whether we should recurse
|
|
|
|
|
// into the AST Node or not. For eg: macros specifying LinkageSpecDecl can
|
|
|
|
|
// have their spelling location defined somewhere outside a source / header
|
|
|
|
|
// file belonging to a library. This should not allow the AST node to be
|
|
|
|
|
// skipped. Its expansion location will still be the source-file / header
|
|
|
|
|
// belonging to the library.
|
|
|
|
|
clang::SourceLocation expansion_location = sm.getExpansionLoc(location);
|
|
|
|
|
llvm::StringRef file_name = sm.getFilename(expansion_location);
|
|
|
|
|
return utils::RealPath(file_name.str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static repr::AccessSpecifierIR AccessClangToIR(
|
|
|
|
|
const clang::AccessSpecifier sp) {
|
|
|
|
|
switch (sp) {
|
|
|
|
|
case clang::AS_private: {
|
|
|
|
|
return repr::AccessSpecifierIR::PrivateAccess;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case clang::AS_protected: {
|
|
|
|
|
return repr::AccessSpecifierIR::ProtectedAccess;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default: {
|
|
|
|
|
return repr::AccessSpecifierIR::PublicAccess;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::CreateAnonymousRecord(const clang::RecordDecl *record_decl) {
|
|
|
|
|
RecordDeclWrapper record_decl_wrapper(mangle_contextp_, ast_contextp_, cip_,
|
|
|
|
|
record_decl, module_, ast_caches_);
|
|
|
|
|
return record_decl_wrapper.GetRecordDecl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get type 'referenced' by qual_type. Referenced type implies, in order:
|
|
|
|
|
// 1) Strip off all qualifiers if qual_type has CVR qualifiers.
|
|
|
|
|
// 2) Strip off a pointer level if qual_type is a pointer.
|
|
|
|
|
@@ -200,6 +211,51 @@ static clang::QualType GetReferencedType(const clang::QualType qual_type) {
|
|
|
|
|
return qual_type.getNonReferenceType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static clang::QualType GetFinalReferencedType(clang::QualType qual_type) {
|
|
|
|
|
while (IsReferencingType(qual_type)) {
|
|
|
|
|
qual_type = GetReferencedType(qual_type);
|
|
|
|
|
}
|
|
|
|
|
return qual_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::TypeNameWithFinalDestination(
|
|
|
|
|
clang::QualType qual_type) {
|
|
|
|
|
clang::QualType canonical_qual_type = qual_type.getCanonicalType();
|
|
|
|
|
const std::string qual_type_name = QualTypeToString(canonical_qual_type);
|
|
|
|
|
clang::QualType final_destination_type =
|
|
|
|
|
GetFinalReferencedType(canonical_qual_type);
|
|
|
|
|
const clang::RecordDecl *anon_record =
|
|
|
|
|
GetAnonymousRecord(final_destination_type);
|
|
|
|
|
if (anon_record) {
|
|
|
|
|
clang::SourceManager &sm = cip_->getSourceManager();
|
|
|
|
|
clang::SourceLocation location = anon_record->getLocation();
|
|
|
|
|
return qual_type_name + " at " + location.printToString(sm);
|
|
|
|
|
}
|
|
|
|
|
return qual_type_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetTypeId(clang::QualType qual_type) {
|
|
|
|
|
return ast_caches_->GetTypeId(GetKeyForTypeId(qual_type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetKeyForTypeId(clang::QualType qual_type) {
|
|
|
|
|
clang::QualType canonical_qual_type = qual_type.getCanonicalType();
|
|
|
|
|
clang::QualType final_destination_type =
|
|
|
|
|
GetFinalReferencedType(canonical_qual_type);
|
|
|
|
|
// Get the tag id for final destionation and add that to the type name with
|
|
|
|
|
// final destination. This helps in avoiding aliasing of types when fully
|
|
|
|
|
// qualified type-name doesn't expand all template parameters with their
|
|
|
|
|
// namespaces.
|
|
|
|
|
return TypeNameWithFinalDestination(qual_type) +
|
|
|
|
|
GetTypeUniqueId(GetTagDecl(final_destination_type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::CreateAnonymousRecord(const clang::RecordDecl *record_decl) {
|
|
|
|
|
RecordDeclWrapper record_decl_wrapper(mangle_contextp_, ast_contextp_, cip_,
|
|
|
|
|
record_decl, module_, ast_caches_);
|
|
|
|
|
return record_decl_wrapper.GetRecordDecl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::CreateExtendedType(clang::QualType qual_type,
|
|
|
|
|
repr::TypeIR *typep) {
|
|
|
|
|
const clang::QualType canonical_type = qual_type.getCanonicalType();
|
|
|
|
|
@@ -207,50 +263,6 @@ bool ABIWrapper::CreateExtendedType(clang::QualType qual_type,
|
|
|
|
|
return CreateBasicNamedAndTypedDecl(canonical_type, typep, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This overload takes in a qualtype and adds its information to the abi-dump on
|
|
|
|
|
// its own.
|
|
|
|
|
bool ABIWrapper::CreateBasicNamedAndTypedDecl(clang::QualType qual_type,
|
|
|
|
|
const std::string &source_file) {
|
|
|
|
|
const std::string &type_key = GetKeyForTypeId(qual_type);
|
|
|
|
|
const clang::QualType canonical_type = qual_type.getCanonicalType();
|
|
|
|
|
const clang::Type *base_type = canonical_type.getTypePtr();
|
|
|
|
|
bool is_builtin = base_type->isBuiltinType();
|
|
|
|
|
bool should_continue_with_recursive_type_creation =
|
|
|
|
|
IsReferencingType(canonical_type) || is_builtin ||
|
|
|
|
|
base_type->isFunctionType() ||
|
|
|
|
|
(GetAnonymousRecord(canonical_type) != nullptr);
|
|
|
|
|
if (!should_continue_with_recursive_type_creation ||
|
|
|
|
|
!ast_caches_->type_cache_.insert(type_key).second) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// Do something similar to what is being done right now. Create an object
|
|
|
|
|
// extending Type and return a pointer to that and pass it to CreateBasic...
|
|
|
|
|
// CreateBasic...(qualtype, Type *) fills in size, alignemnt etc.
|
|
|
|
|
auto type_and_status = SetTypeKind(canonical_type, source_file);
|
|
|
|
|
std::unique_ptr<repr::TypeIR> typep = std::move(type_and_status.typep_);
|
|
|
|
|
if (!base_type->isVoidType() && type_and_status.should_create_type_ &&
|
|
|
|
|
!typep) {
|
|
|
|
|
llvm::errs() << "nullptr with valid type while creating basic type\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!type_and_status.should_create_type_) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return (CreateBasicNamedAndTypedDecl(
|
|
|
|
|
canonical_type, typep.get(), source_file) &&
|
|
|
|
|
module_->AddLinkableMessage(*typep));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string RecordDeclWrapper::GetMangledRTTI(
|
|
|
|
|
const clang::CXXRecordDecl *cxx_record_decl) {
|
|
|
|
|
clang::QualType qual_type =
|
|
|
|
|
cxx_record_decl->getTypeForDecl()->getCanonicalTypeInternal();
|
|
|
|
|
llvm::SmallString<256> uid;
|
|
|
|
|
llvm::raw_svector_ostream out(uid);
|
|
|
|
|
mangle_contextp_->mangleCXXRTTI(qual_type, out);
|
|
|
|
|
return uid.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetTypeUniqueId(const clang::TagDecl *tag_decl) {
|
|
|
|
|
if (!tag_decl) {
|
|
|
|
|
return "";
|
|
|
|
|
@@ -277,36 +289,68 @@ bool ABIWrapper::CreateBasicNamedAndTypedDecl(
|
|
|
|
|
const clang::Type *base_type = canonical_type.getTypePtr();
|
|
|
|
|
assert(base_type != nullptr);
|
|
|
|
|
clang::Type::TypeClass type_class = base_type->getTypeClass();
|
|
|
|
|
// Temporary hack for auto type sizes. Not determinable.
|
|
|
|
|
if ((type_class != clang::Type::Auto) && !base_type->isIncompleteType() &&
|
|
|
|
|
!(base_type->isDependentType())) {
|
|
|
|
|
|
|
|
|
|
// Set the size and alignment of the type.
|
|
|
|
|
// Temporary hack: Skip the auto types, incomplete types and dependent types.
|
|
|
|
|
if (type_class != clang::Type::Auto && !base_type->isIncompleteType() &&
|
|
|
|
|
!base_type->isDependentType()) {
|
|
|
|
|
std::pair<clang::CharUnits, clang::CharUnits> size_and_alignment =
|
|
|
|
|
ast_contextp_->getTypeInfoInChars(canonical_type);
|
|
|
|
|
size_t size = size_and_alignment.first.getQuantity();
|
|
|
|
|
size_t alignment = size_and_alignment.second.getQuantity();
|
|
|
|
|
typep->SetSize(size);
|
|
|
|
|
typep->SetAlignment(alignment);
|
|
|
|
|
typep->SetSize(size_and_alignment.first.getQuantity());
|
|
|
|
|
typep->SetAlignment(size_and_alignment.second.getQuantity());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string type_name_with_destination =
|
|
|
|
|
TypeNameWithFinalDestination(canonical_type);
|
|
|
|
|
typep->SetName(type_name_with_destination);
|
|
|
|
|
typep->SetLinkerSetKey(type_name_with_destination);
|
|
|
|
|
// Default values are false, we don't set them since explicitly doing that
|
|
|
|
|
// makes the ABI dumps more verbose.
|
|
|
|
|
|
|
|
|
|
// This type has a reference type if its a pointer / reference OR it has CVR
|
|
|
|
|
// qualifiers.
|
|
|
|
|
clang::QualType referenced_type = GetReferencedType(canonical_type);
|
|
|
|
|
typep->SetReferencedType(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(referenced_type)));
|
|
|
|
|
typep->SetSelfType(ast_caches_->GetTypeId(GetKeyForTypeId(canonical_type)));
|
|
|
|
|
typep->SetReferencedType(GetTypeId(referenced_type));
|
|
|
|
|
|
|
|
|
|
typep->SetSelfType(GetTypeId(canonical_type));
|
|
|
|
|
|
|
|
|
|
// Create the type for referenced type.
|
|
|
|
|
return CreateBasicNamedAndTypedDecl(referenced_type, source_file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetTypeLinkageName(const clang::Type *typep) {
|
|
|
|
|
assert(typep != nullptr);
|
|
|
|
|
clang::QualType qt = typep->getCanonicalTypeInternal();
|
|
|
|
|
return QualTypeToString(qt);
|
|
|
|
|
// This overload takes in a qualtype and adds its information to the abi-dump on
|
|
|
|
|
// its own.
|
|
|
|
|
bool ABIWrapper::CreateBasicNamedAndTypedDecl(clang::QualType qual_type,
|
|
|
|
|
const std::string &source_file) {
|
|
|
|
|
const std::string &type_key = GetKeyForTypeId(qual_type);
|
|
|
|
|
const clang::QualType canonical_type = qual_type.getCanonicalType();
|
|
|
|
|
const clang::Type *base_type = canonical_type.getTypePtr();
|
|
|
|
|
bool is_builtin = base_type->isBuiltinType();
|
|
|
|
|
bool should_continue_with_recursive_type_creation =
|
|
|
|
|
IsReferencingType(canonical_type) || is_builtin ||
|
|
|
|
|
base_type->isFunctionType() ||
|
|
|
|
|
(GetAnonymousRecord(canonical_type) != nullptr);
|
|
|
|
|
if (!should_continue_with_recursive_type_creation ||
|
|
|
|
|
!ast_caches_->type_cache_.insert(type_key).second) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Do something similar to what is being done right now. Create an object
|
|
|
|
|
// extending Type and return a pointer to that and pass it to CreateBasic...
|
|
|
|
|
// CreateBasic...(qualtype, Type *) fills in size, alignemnt etc.
|
|
|
|
|
auto type_and_status = SetTypeKind(canonical_type, source_file);
|
|
|
|
|
std::unique_ptr<repr::TypeIR> typep = std::move(type_and_status.typep_);
|
|
|
|
|
if (!base_type->isVoidType() && type_and_status.should_create_type_ &&
|
|
|
|
|
!typep) {
|
|
|
|
|
llvm::errs() << "nullptr with valid type while creating basic type\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!type_and_status.should_create_type_) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (CreateBasicNamedAndTypedDecl(
|
|
|
|
|
canonical_type, typep.get(), source_file) &&
|
|
|
|
|
module_->AddLinkableMessage(*typep));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This method returns a TypeAndCreationStatus object. This object contains a
|
|
|
|
|
@@ -379,49 +423,6 @@ TypeAndCreationStatus ABIWrapper::SetTypeKind(
|
|
|
|
|
return TypeAndCreationStatus(nullptr, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetMangledNameDecl(
|
|
|
|
|
const clang::NamedDecl *decl, clang::MangleContext *mangle_contextp) {
|
|
|
|
|
if (!mangle_contextp->shouldMangleDeclName(decl)) {
|
|
|
|
|
clang::IdentifierInfo *identifier = decl->getIdentifier();
|
|
|
|
|
return identifier ? identifier->getName() : "";
|
|
|
|
|
}
|
|
|
|
|
std::string mangled_name;
|
|
|
|
|
llvm::raw_string_ostream ostream(mangled_name);
|
|
|
|
|
mangle_contextp->mangleName(decl, ostream);
|
|
|
|
|
ostream.flush();
|
|
|
|
|
return mangled_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::GetTagDeclQualifiedName(const clang::TagDecl *decl) {
|
|
|
|
|
if (decl->getTypedefNameForAnonDecl()) {
|
|
|
|
|
return decl->getTypedefNameForAnonDecl()->getQualifiedNameAsString();
|
|
|
|
|
}
|
|
|
|
|
return decl->getQualifiedNameAsString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::SetupTemplateArguments(const clang::TemplateArgumentList *tl,
|
|
|
|
|
repr::TemplatedArtifactIR *ta,
|
|
|
|
|
const std::string &source_file) {
|
|
|
|
|
repr::TemplateInfoIR template_info;
|
|
|
|
|
for (int i = 0; i < tl->size(); i++) {
|
|
|
|
|
const clang::TemplateArgument &arg = (*tl)[i];
|
|
|
|
|
// TODO: More comprehensive checking needed.
|
|
|
|
|
if (arg.getKind() != clang::TemplateArgument::Type) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
clang::QualType type = arg.getAsType();
|
|
|
|
|
template_info.AddTemplateElement(
|
|
|
|
|
repr::TemplateElementIR(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(type))));
|
|
|
|
|
if (!CreateBasicNamedAndTypedDecl(type, source_file)) {
|
|
|
|
|
llvm::errs() << "Setting up template arguments failed\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ta->SetTemplateInfo(std::move(template_info));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ABIWrapper::QualTypeToString(const clang::QualType &sweet_qt) {
|
|
|
|
|
const clang::QualType salty_qt = sweet_qt.getCanonicalType();
|
|
|
|
|
// clang::TypeName::getFullyQualifiedName removes the part of the type related
|
|
|
|
|
@@ -433,6 +434,11 @@ std::string ABIWrapper::QualTypeToString(const clang::QualType &sweet_qt) {
|
|
|
|
|
salty_qt, *ast_contextp_, ast_contextp_->getPrintingPolicy());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// Function Type Wrapper
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
FunctionTypeWrapper::FunctionTypeWrapper(
|
|
|
|
|
clang::MangleContext *mangle_contextp, clang::ASTContext *ast_contextp,
|
|
|
|
|
const clang::CompilerInstance *compiler_instance_p,
|
|
|
|
|
@@ -446,8 +452,7 @@ FunctionTypeWrapper::FunctionTypeWrapper(
|
|
|
|
|
bool FunctionTypeWrapper::SetupFunctionType(
|
|
|
|
|
repr::FunctionTypeIR *function_type_ir) {
|
|
|
|
|
// Add ReturnType
|
|
|
|
|
function_type_ir->SetReturnType(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(function_type_->getReturnType())));
|
|
|
|
|
function_type_ir->SetReturnType(GetTypeId(function_type_->getReturnType()));
|
|
|
|
|
function_type_ir->SetSourceFile(source_file_);
|
|
|
|
|
const clang::FunctionProtoType *function_pt =
|
|
|
|
|
llvm::dyn_cast<clang::FunctionProtoType>(function_type_);
|
|
|
|
|
@@ -475,6 +480,11 @@ bool FunctionTypeWrapper::GetFunctionType() {
|
|
|
|
|
module_->AddLinkableMessage(*abi_decl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// Function Decl Wrapper
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
FunctionDeclWrapper::FunctionDeclWrapper(
|
|
|
|
|
clang::MangleContext *mangle_contextp,
|
|
|
|
|
clang::ASTContext *ast_contextp,
|
|
|
|
|
@@ -498,19 +508,6 @@ bool FunctionDeclWrapper::SetupThisParameter(repr::FunctionIR *functionp,
|
|
|
|
|
return SetupFunctionParameter(functionp, this_type, false, source_file, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ABIWrapper::SetupFunctionParameter(
|
|
|
|
|
repr::CFunctionLikeIR *functionp, const clang::QualType qual_type,
|
|
|
|
|
bool has_default_arg, const std::string &source_file, bool is_this_ptr) {
|
|
|
|
|
if (!CreateBasicNamedAndTypedDecl(qual_type, source_file)) {
|
|
|
|
|
llvm::errs() << "Setting up function parameter failed\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
functionp->AddParameter(repr::ParamIR(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(qual_type)), has_default_arg,
|
|
|
|
|
is_this_ptr));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FunctionDeclWrapper::SetupFunctionParameters(
|
|
|
|
|
repr::FunctionIR *functionp,
|
|
|
|
|
const std::string &source_file) {
|
|
|
|
|
@@ -544,8 +541,7 @@ bool FunctionDeclWrapper::SetupFunction(repr::FunctionIR *functionp,
|
|
|
|
|
functionp->SetSourceFile(source_file);
|
|
|
|
|
clang::QualType return_type = function_decl_->getReturnType();
|
|
|
|
|
|
|
|
|
|
functionp->SetReturnType(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(return_type)));
|
|
|
|
|
functionp->SetReturnType(GetTypeId(return_type));
|
|
|
|
|
functionp->SetAccess(AccessClangToIR(function_decl_->getAccess()));
|
|
|
|
|
return CreateBasicNamedAndTypedDecl(return_type, source_file) &&
|
|
|
|
|
SetupFunctionParameters(functionp, source_file) &&
|
|
|
|
|
@@ -580,6 +576,11 @@ std::unique_ptr<repr::FunctionIR> FunctionDeclWrapper::GetFunctionDecl() {
|
|
|
|
|
return abi_decl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// Record Decl Wrapper
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
RecordDeclWrapper::RecordDeclWrapper(
|
|
|
|
|
clang::MangleContext *mangle_contextp,
|
|
|
|
|
clang::ASTContext *ast_contextp,
|
|
|
|
|
@@ -598,11 +599,9 @@ bool RecordDeclWrapper::SetupRecordFields(repr::RecordTypeIR *recordp,
|
|
|
|
|
ast_contextp_->getASTRecordLayout(record_decl_);
|
|
|
|
|
while (field != record_decl_->field_end()) {
|
|
|
|
|
clang::QualType field_type = field->getType();
|
|
|
|
|
std::string key_for_type_id = GetKeyForTypeId(field_type);
|
|
|
|
|
if (const clang::EnumDecl *enum_decl =
|
|
|
|
|
GetAnonymousEnum(field_type)) {
|
|
|
|
|
if (const clang::EnumDecl *enum_decl = GetAnonymousEnum(field_type)) {
|
|
|
|
|
// Handle anonymous enums.
|
|
|
|
|
key_for_type_id = GetKeyForTypeId(enum_decl->getIntegerType());
|
|
|
|
|
field_type = enum_decl->getIntegerType();
|
|
|
|
|
}
|
|
|
|
|
if (!CreateBasicNamedAndTypedDecl(field_type, source_file)) {
|
|
|
|
|
llvm::errs() << "Creation of Type failed\n";
|
|
|
|
|
@@ -611,7 +610,7 @@ bool RecordDeclWrapper::SetupRecordFields(repr::RecordTypeIR *recordp,
|
|
|
|
|
std::string field_name = field->getName();
|
|
|
|
|
uint64_t field_offset = record_layout.getFieldOffset(field_index);
|
|
|
|
|
recordp->AddRecordField(repr::RecordFieldIR(
|
|
|
|
|
field_name, ast_caches_->GetTypeId(key_for_type_id), field_offset,
|
|
|
|
|
field_name, GetTypeId(field_type), field_offset,
|
|
|
|
|
AccessClangToIR(field->getAccess())));
|
|
|
|
|
field++;
|
|
|
|
|
field_index++;
|
|
|
|
|
@@ -627,14 +626,11 @@ bool RecordDeclWrapper::SetupCXXBases(
|
|
|
|
|
clang::CXXRecordDecl::base_class_const_iterator base_class =
|
|
|
|
|
cxx_record_decl->bases_begin();
|
|
|
|
|
while (base_class != cxx_record_decl->bases_end()) {
|
|
|
|
|
std::string name = QualTypeToString(base_class->getType());
|
|
|
|
|
bool is_virtual = base_class->isVirtual();
|
|
|
|
|
repr::AccessSpecifierIR access =
|
|
|
|
|
AccessClangToIR(base_class->getAccessSpecifier());
|
|
|
|
|
cxxp->AddCXXBaseSpecifier(
|
|
|
|
|
repr::CXXBaseSpecifierIR(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(base_class->getType())),
|
|
|
|
|
is_virtual, access));
|
|
|
|
|
cxxp->AddCXXBaseSpecifier(repr::CXXBaseSpecifierIR(
|
|
|
|
|
GetTypeId(base_class->getType()), is_virtual, access));
|
|
|
|
|
base_class++;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
@@ -858,6 +854,21 @@ bool RecordDeclWrapper::GetRecordDecl() {
|
|
|
|
|
return module_->AddLinkableMessage(*abi_decl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string RecordDeclWrapper::GetMangledRTTI(
|
|
|
|
|
const clang::CXXRecordDecl *cxx_record_decl) {
|
|
|
|
|
clang::QualType qual_type =
|
|
|
|
|
cxx_record_decl->getTypeForDecl()->getCanonicalTypeInternal();
|
|
|
|
|
llvm::SmallString<256> uid;
|
|
|
|
|
llvm::raw_svector_ostream out(uid);
|
|
|
|
|
mangle_contextp_->mangleCXXRTTI(qual_type, out);
|
|
|
|
|
return uid.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// Enum Decl Wrapper
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
EnumDeclWrapper::EnumDeclWrapper(
|
|
|
|
|
clang::MangleContext *mangle_contextp,
|
|
|
|
|
clang::ASTContext *ast_contextp,
|
|
|
|
|
@@ -884,15 +895,13 @@ bool EnumDeclWrapper::SetupEnumFields(repr::EnumTypeIR *enump) {
|
|
|
|
|
|
|
|
|
|
bool EnumDeclWrapper::SetupEnum(repr::EnumTypeIR *enum_type,
|
|
|
|
|
const std::string &source_file) {
|
|
|
|
|
std::string enum_name = GetTagDeclQualifiedName(enum_decl_);
|
|
|
|
|
clang::QualType enum_qual_type =
|
|
|
|
|
enum_decl_->getTypeForDecl()->getCanonicalTypeInternal();
|
|
|
|
|
if (!CreateExtendedType(enum_qual_type, enum_type)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
enum_type->SetSourceFile(source_file);
|
|
|
|
|
enum_type->SetUnderlyingType(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(enum_decl_->getIntegerType())));
|
|
|
|
|
enum_type->SetUnderlyingType(GetTypeId(enum_decl_->getIntegerType()));
|
|
|
|
|
enum_type->SetAccess(AccessClangToIR(enum_decl_->getAccess()));
|
|
|
|
|
enum_type->SetUniqueId(GetTypeUniqueId(enum_decl_));
|
|
|
|
|
return SetupEnumFields(enum_type) &&
|
|
|
|
|
@@ -910,6 +919,11 @@ bool EnumDeclWrapper::GetEnumDecl() {
|
|
|
|
|
return module_->AddLinkableMessage(*abi_decl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
// Global Decl Wrapper
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
GlobalVarDeclWrapper::GlobalVarDeclWrapper(
|
|
|
|
|
clang::MangleContext *mangle_contextp,
|
|
|
|
|
clang::ASTContext *ast_contextp,
|
|
|
|
|
@@ -933,8 +947,7 @@ bool GlobalVarDeclWrapper::SetupGlobalVar(repr::GlobalVarIR *global_varp,
|
|
|
|
|
global_varp->SetName(global_var_decl_->getQualifiedNameAsString());
|
|
|
|
|
global_varp->SetLinkerSetKey(mangled_name);
|
|
|
|
|
global_varp->SetAccess(AccessClangToIR(global_var_decl_->getAccess()));
|
|
|
|
|
global_varp->SetReferencedType(
|
|
|
|
|
ast_caches_->GetTypeId(GetKeyForTypeId(global_var_decl_->getType())));
|
|
|
|
|
global_varp->SetReferencedType(GetTypeId(global_var_decl_->getType()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|