Home | History | Annotate | Download | only in src
      1 // Copyright (C) 2016 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "ast_processing.h"
     16 #include "abi_wrappers.h"
     17 
     18 #include <clang/Lex/Token.h>
     19 #include <clang/Tooling/Core/QualTypeNames.h>
     20 #include <clang/Index/CodegenNameGenerator.h>
     21 
     22 #include <fstream>
     23 #include <iostream>
     24 #include <string>
     25 
     26 using abi_wrapper::ABIWrapper;
     27 using abi_wrapper::FunctionDeclWrapper;
     28 using abi_wrapper::RecordDeclWrapper;
     29 using abi_wrapper::EnumDeclWrapper;
     30 using abi_wrapper::GlobalVarDeclWrapper;
     31 
     32 HeaderASTVisitor::HeaderASTVisitor(
     33     clang::MangleContext *mangle_contextp,
     34     clang::ASTContext *ast_contextp,
     35     const clang::CompilerInstance *compiler_instance_p,
     36     const std::set<std::string> &exported_headers,
     37     const clang::Decl *tu_decl,
     38     abi_util::IRDumper *ir_dumper,
     39     ast_util::ASTCaches *ast_caches)
     40   : mangle_contextp_(mangle_contextp),
     41     ast_contextp_(ast_contextp),
     42     cip_(compiler_instance_p),
     43     exported_headers_(exported_headers),
     44     tu_decl_(tu_decl),
     45     ir_dumper_(ir_dumper),
     46     ast_caches_(ast_caches) { }
     47 
     48 bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
     49   // Skip forward declarations, dependent records. Also skip anonymous records
     50   // as they will be traversed through record fields.
     51   if (!decl->isThisDeclarationADefinition() ||
     52       decl->getTypeForDecl()->isDependentType() ||
     53       decl->isAnonymousStructOrUnion() ||
     54       !decl->hasNameForLinkage() ||
     55       !decl->isExternallyVisible()) {
     56     return true;
     57   }
     58   RecordDeclWrapper record_decl_wrapper(
     59       mangle_contextp_, ast_contextp_, cip_, decl, ir_dumper_, ast_caches_);
     60   return record_decl_wrapper.GetRecordDecl();
     61 }
     62 
     63 bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) {
     64   if (!decl->isThisDeclarationADefinition() ||
     65       decl->getTypeForDecl()->isDependentType() ||
     66       !decl->hasNameForLinkage()) {
     67     return true;
     68   }
     69   EnumDeclWrapper enum_decl_wrapper(
     70       mangle_contextp_, ast_contextp_, cip_, decl, ir_dumper_, ast_caches_);
     71   return enum_decl_wrapper.GetEnumDecl();
     72  }
     73 
     74 static bool MutateFunctionWithLinkageName(const abi_util::FunctionIR *function,
     75                                           abi_util::IRDumper *ir_dumper,
     76                                           std::string &linkage_name) {
     77   auto added_function = std::make_unique<abi_util::FunctionIR>();
     78   *added_function = *function;
     79   added_function->SetLinkerSetKey(linkage_name);
     80   return ir_dumper->AddLinkableMessageIR(added_function.get());
     81 }
     82 
     83 static bool AddMangledFunctions(const abi_util::FunctionIR *function,
     84                                 abi_util:: IRDumper *ir_dumper,
     85                                 std::vector<std::string> &manglings) {
     86   for (auto &&mangling : manglings) {
     87     if (!MutateFunctionWithLinkageName(function, ir_dumper, mangling)) {
     88       return false;
     89     }
     90   }
     91   return true;
     92 }
     93 
     94 static bool ShouldSkipFunctionDecl(const clang::FunctionDecl *decl) {
     95   if (!decl->getDefinition()) {
     96     return true;
     97   }
     98   if (decl->getLinkageAndVisibility().getLinkage() !=
     99       clang::Linkage::ExternalLinkage) {
    100     return true;
    101   }
    102   if (const clang::CXXMethodDecl *method_decl =
    103       llvm::dyn_cast<clang::CXXMethodDecl>(decl)) {
    104     if (method_decl->getParent()->getTypeForDecl()->isDependentType()) {
    105       return true;
    106     }
    107   }
    108   clang::FunctionDecl::TemplatedKind tkind = decl->getTemplatedKind();
    109   switch (tkind) {
    110     case clang::FunctionDecl::TK_NonTemplate:
    111     case clang::FunctionDecl::TK_FunctionTemplateSpecialization:
    112     case clang::FunctionDecl::TK_MemberSpecialization:
    113       return false;
    114     default:
    115       return true;
    116   }
    117 }
    118 
    119 bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) {
    120   if (ShouldSkipFunctionDecl(decl)) {
    121     return true;
    122   }
    123   FunctionDeclWrapper function_decl_wrapper(mangle_contextp_, ast_contextp_,
    124                                             cip_, decl, ir_dumper_,
    125                                             ast_caches_);
    126   auto function_wrapper = function_decl_wrapper.GetFunctionDecl();
    127   // Destructors and Constructors can have more than 1 symbol generated from the
    128   // same Decl.
    129   clang::index::CodegenNameGenerator cg(*ast_contextp_);
    130   std::vector<std::string> manglings = cg.getAllManglings(decl);
    131   if (!manglings.empty()) {
    132     return AddMangledFunctions(function_wrapper.get(), ir_dumper_, manglings);
    133   }
    134   std::string linkage_name =
    135       ABIWrapper::GetMangledNameDecl(decl, mangle_contextp_);
    136   return MutateFunctionWithLinkageName(function_wrapper.get(), ir_dumper_,
    137                                        linkage_name);
    138 }
    139 
    140 bool HeaderASTVisitor::VisitVarDecl(const clang::VarDecl *decl) {
    141   if(!decl->hasGlobalStorage()||
    142      decl->getType().getTypePtr()->isDependentType()) {
    143     // Non global / static variable declarations don't need to be dumped.
    144     return true;
    145   }
    146   GlobalVarDeclWrapper global_var_decl_wrapper(mangle_contextp_, ast_contextp_,
    147                                                cip_, decl, ir_dumper_,
    148                                                ast_caches_);
    149   return  global_var_decl_wrapper.GetGlobalVarDecl();
    150 }
    151 
    152 static bool AreHeadersExported(const std::set<std::string> &exported_headers) {
    153   return !exported_headers.empty();
    154 }
    155 
    156 // We don't need to recurse into Declarations which are not exported.
    157 bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
    158   if (!decl) {
    159     return true;
    160   }
    161   std::string source_file = ABIWrapper::GetDeclSourceFile(decl, cip_);
    162   ast_caches_->decl_to_source_file_cache_.insert(
    163       std::make_pair(decl, source_file));
    164   // If no exported headers are specified we assume the whole AST is exported.
    165   if ((decl != tu_decl_) && AreHeadersExported(exported_headers_) &&
    166       (exported_headers_.find(source_file) == exported_headers_.end())) {
    167     return true;
    168   }
    169   // If at all we're looking at the source file's AST decl node, it should be a
    170   // function decl node.
    171   if ((decl != tu_decl_) &&
    172       (source_file == ast_caches_->translation_unit_source_) &&
    173       !decl->isFunctionOrFunctionTemplate()) {
    174     return true;
    175   }
    176   return RecursiveASTVisitor<HeaderASTVisitor>::TraverseDecl(decl);
    177 }
    178 
    179 HeaderASTConsumer::HeaderASTConsumer(
    180     clang::CompilerInstance *compiler_instancep,
    181     const std::string &out_dump_name,
    182     std::set<std::string> &exported_headers,
    183     abi_util::TextFormatIR text_format)
    184   : cip_(compiler_instancep),
    185     out_dump_name_(out_dump_name),
    186     exported_headers_(exported_headers),
    187     text_format_(text_format){ }
    188 
    189 void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
    190   clang::PrintingPolicy policy(ctx.getPrintingPolicy());
    191   // Suppress 'struct' keyword for C source files while getting QualType string
    192   // names to avoid inconsistency between C and C++ (for C++ files, this is true
    193   // by default)
    194   policy.SuppressTagKeyword = true;
    195   ctx.setPrintingPolicy(policy);
    196   clang::TranslationUnitDecl *translation_unit = ctx.getTranslationUnitDecl();
    197   std::unique_ptr<clang::MangleContext> mangle_contextp(
    198       ctx.createMangleContext());
    199   const std::string &translation_unit_source =
    200       ABIWrapper::GetDeclSourceFile(translation_unit, cip_);
    201   ast_util::ASTCaches ast_caches(translation_unit_source);
    202   if (!exported_headers_.empty()) {
    203     exported_headers_.insert(translation_unit_source);
    204   }
    205   std::unique_ptr<abi_util::IRDumper> ir_dumper =
    206       abi_util::IRDumper::CreateIRDumper(text_format_, out_dump_name_);
    207   HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, exported_headers_,
    208                      translation_unit, ir_dumper.get(), &ast_caches);
    209 
    210   if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) {
    211     llvm::errs() << "Serialization to ostream failed\n";
    212     ::exit(1);
    213   }
    214 }
    215