brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · 7313a93 Raw
200 lines · cpp
1//===--- MacroPPCallbacks.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file contains implementation for the macro preprocessors callbacks.10//11//===----------------------------------------------------------------------===//12 13#include "MacroPPCallbacks.h"14#include "CGDebugInfo.h"15#include "clang/CodeGen/ModuleBuilder.h"16#include "clang/Lex/MacroInfo.h"17#include "clang/Lex/Preprocessor.h"18 19using namespace clang;20 21void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II,22                                            const MacroInfo &MI,23                                            Preprocessor &PP, raw_ostream &Name,24                                            raw_ostream &Value) {25  Name << II.getName();26 27  if (MI.isFunctionLike()) {28    Name << '(';29    if (!MI.param_empty()) {30      MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end();31      for (; AI + 1 != E; ++AI) {32        Name << (*AI)->getName();33        Name << ',';34      }35 36      // Last argument.37      if ((*AI)->getName() == "__VA_ARGS__")38        Name << "...";39      else40        Name << (*AI)->getName();41    }42 43    if (MI.isGNUVarargs())44      // #define foo(x...)45      Name << "...";46 47    Name << ')';48  }49 50  SmallString<128> SpellingBuffer;51  bool First = true;52  for (const auto &T : MI.tokens()) {53    if (!First && T.hasLeadingSpace())54      Value << ' ';55 56    Value << PP.getSpelling(T, SpellingBuffer);57    First = false;58  }59}60 61MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)62    : Gen(Gen), PP(PP), Status(NoScope) {}63 64// This is the expected flow of enter/exit compiler and user files:65// - Main File Enter66//   - <built-in> file enter67//     {Compiler macro definitions} - (Line=0, no scope)68//     - (Optional) <command line> file enter69//     {Command line macro definitions} - (Line=0, no scope)70//     - (Optional) <command line> file exit71//     {Command line file includes} - (Line=0, Main file scope)72//       {macro definitions and file includes} - (Line!=0, Parent scope)73//   - <built-in> file exit74//   {User code macro definitions and file includes} - (Line!=0, Parent scope)75 76llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {77  if (Status == MainFileScope || Status == CommandLineIncludeScope)78    return Scopes.back();79  return nullptr;80}81 82SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {83  if (Status == MainFileScope || EnteredCommandLineIncludeFiles)84    return Loc;85 86  // While parsing skipped files, location of macros is invalid.87  // Invalid location represents line zero.88  return SourceLocation();89}90 91void MacroPPCallbacks::updateStatusToNextScope() {92  switch (Status) {93  case NoScope:94    Status = InitializedScope;95    break;96  case InitializedScope:97    Status = BuiltinScope;98    break;99  case BuiltinScope:100    Status = CommandLineIncludeScope;101    break;102  case CommandLineIncludeScope:103    Status = MainFileScope;104    break;105  case MainFileScope:106    llvm_unreachable("There is no next scope, already in the final scope");107  }108}109 110void MacroPPCallbacks::FileEntered(SourceLocation Loc) {111  SourceLocation LineLoc = getCorrectLocation(LastHashLoc);112  switch (Status) {113  case NoScope:114    updateStatusToNextScope();115    break;116  case InitializedScope:117    updateStatusToNextScope();118    return;119  case BuiltinScope:120    if (PP.getSourceManager().isWrittenInCommandLineFile(Loc))121      return;122    updateStatusToNextScope();123    [[fallthrough]];124  case CommandLineIncludeScope:125    EnteredCommandLineIncludeFiles++;126    break;127  case MainFileScope:128    break;129  }130 131  Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),132                                                              LineLoc, Loc));133}134 135void MacroPPCallbacks::FileExited(SourceLocation Loc) {136  switch (Status) {137  default:138    llvm_unreachable("Do not expect to exit a file from current scope");139  case BuiltinScope:140    if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc))141      // Skip next scope and change status to MainFileScope.142      Status = MainFileScope;143    return;144  case CommandLineIncludeScope:145    if (!EnteredCommandLineIncludeFiles) {146      updateStatusToNextScope();147      return;148    }149    EnteredCommandLineIncludeFiles--;150    break;151  case MainFileScope:152    break;153  }154 155  Scopes.pop_back();156}157 158void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,159                                   SrcMgr::CharacteristicKind FileType,160                                   FileID PrevFID) {161  // Only care about enter file or exit file changes.162  if (Reason == EnterFile)163    FileEntered(Loc);164  else if (Reason == ExitFile)165    FileExited(Loc);166}167 168void MacroPPCallbacks::InclusionDirective(169    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,170    bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,171    StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,172    bool ModuleImported, SrcMgr::CharacteristicKind FileType) {173 174  // Record the line location of the current included file.175  LastHashLoc = HashLoc;176}177 178void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,179                                    const MacroDirective *MD) {180  IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();181  SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());182  std::string NameBuffer, ValueBuffer;183  llvm::raw_string_ostream Name(NameBuffer);184  llvm::raw_string_ostream Value(ValueBuffer);185  writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);186  Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),187                                     llvm::dwarf::DW_MACINFO_define, location,188                                     NameBuffer, ValueBuffer);189}190 191void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,192                                      const MacroDefinition &MD,193                                      const MacroDirective *Undef) {194  IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();195  SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());196  Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),197                                     llvm::dwarf::DW_MACINFO_undef, location,198                                     Id->getName(), "");199}200