Beispiel #1
0
void Resolve::runOnFunction(Function *F) {
  for (auto &Arg : F->args())
    if (!K->Map.add(Arg, F->getEntryBlock())) {
      DiagnosticPrinter(Arg->getSourceLocation())
          << "argument " + Arg->getName() + " attempting to overshadow "
                                            "previously bound symbol with "
                                            "same name";
    }

  /// For all statements of the form:
  ///   %V = 7;
  ///      ^
  ///   BindInst
  ///
  /// Insert into K->Map
  for (auto &BB : *F)
    for (auto &V : *BB) {
      if (auto B = dyn_cast<BindInst>(V))
        if (!K->Map.add(B, BB)) {
          DiagnosticPrinter(B->getSourceLocation())
              << "symbol " + B->getName() + " attempting to overshadow "
                                            "previously bound symbol with same "
                                            "name";
          exit(1);
        }
    }

  /// Resolve operands of all Users:
  ///   %V(...);
  ///    ^  ^---- Operands
  ///   User
  for (auto &BB : *F)
    for (auto &V : *BB)
      resolveOperandsOfUser(cast<User>(V), BB);
}
Beispiel #2
0
bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (const std::string &Str : CommandLine)
    Argv.push_back(Str.c_str());
  const char *const BinaryName = Argv[0];
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), &*DiagOpts);
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
      DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);

  const std::unique_ptr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const std::unique_ptr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (CC1Args == NULL) {
    return false;
  }
  std::unique_ptr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  for (const auto &It : MappedFileContents) {
    // Inject the code as the given file name into the preprocessor options.
    auto *Input = llvm::MemoryBuffer::getMemBuffer(It.getValue());
    Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(), Input);
  }
  return runInvocation(BinaryName, Compilation.get(), Invocation.release());
}
Beispiel #3
0
llvm::Constant *Function::toLL(llvm::Module *M) {
  auto K = getContext();
  auto CurrentFunction = getOrInsert(M);

  /// Bind argument symbols to function argument values in symbol table
  auto ArgList = getArguments();
  auto S = ArgList.begin();
  for (auto &Arg : CurrentFunction->args()) {
    auto SourceLoc = (*S)->getSourceLocation();
    if (!K->Map.add(*S, &Arg))
      DiagnosticPrinter(SourceLoc)
          << "argument " + (*S)->getName() +
                 " conflicts with existing symbol name";
    ++S;
  }

  // Add function symbol to symbol table, global scope
  K->Map.add(this, CurrentFunction);

  /// Codegens all blocks
  getEntryBlock()->toLL(M);

  auto ExitBlock = getExitBlock();
  if (!ExitBlock->size() || !isa<ReturnInst>(ExitBlock->back()))
    K->Builder->CreateRet(nullptr);
  return CurrentFunction;
}
Beispiel #4
0
Type *TypeInfer::visit(Argument *V) {
  if (!V->isUnTyped())
    return V->getType();
  DiagnosticPrinter(V->getSourceLocation())
      << "untyped argument " + V->getName();
  exit(1);
}
Beispiel #5
0
bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (int I = 0, E = CommandLine.size(); I != E; ++I)
    Argv.push_back(CommandLine[I].c_str());
  const char *const BinaryName = Argv[0];
  DiagnosticOptions DefaultDiagnosticOptions;
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), DefaultDiagnosticOptions);
  DiagnosticsEngine Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(
      new DiagnosticIDs()), &DiagnosticPrinter, false);

  const llvm::OwningPtr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const llvm::OwningPtr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  const clang::driver::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (CC1Args == NULL) {
    return false;
  }
  llvm::OwningPtr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  return runInvocation(BinaryName, Compilation.get(),
                       Invocation.take(), *CC1Args, ToolAction.take());
}
Beispiel #6
0
Type *TypeInfer::visit(LoadInst *V) {
  V->setType(V->getVal()->getType());
  if (!V->isUnTyped())
    return V->getType();
  auto Name = V->getVal()->getName();
  DiagnosticPrinter(V->getSourceLocation()) << "untyped symbol " + Name;
  exit(1);
}
Beispiel #7
0
void Resolve::lookupReplaceUse(UnresolvedValue *V, Use &U, BasicBlock *Block) {
  auto Name = V->getName();
  auto K = V->getContext();
  if (auto S = K->Map.get(V, Block)) {
    /// %S = 2;
    ///  ^
    /// Came from here (MallocInst, Argument, or Prototype)
    ///
    /// Foo(%S);
    ///      ^
    ///  UnresolvedValue; replace with %Replacement
    if (auto M = dyn_cast<MallocInst>(S)) {
      if (dyn_cast<StoreInst>(U->getUser()))
        U.set(M);
      else {
        auto Replacement = LoadInst::get(M);
        Replacement->setSourceLocation(V->getSourceLocation());
        U.set(Replacement);
      }
    } else if (isa<BindInst>(S) || isa<Argument>(S)) {
      U.set(S);
    } else if (isa<Prototype>(S)) {
      auto Replacement = Pointer::get(S);
      Replacement->setSourceLocation(S->getSourceLocation());
      U.set(Replacement);
    }
  } else {
    /// %V was not seen earlier (%S not initialized)
    /// Only one possibility: %V(...)
    ///                        ^
    ///                Callee of CallInst
    auto SourceLoc = U->getSourceLocation();
    if (auto Inst = dyn_cast<CallInst>(U->getUser()))
      if (Inst->getCallee() == V) {
        DiagnosticPrinter(SourceLoc) << "unbound function " + Name;
        exit(1);
      }
    DiagnosticPrinter(SourceLoc) << "unbound symbol " + Name;
    exit(1);
  }
}
Beispiel #8
0
FunctionType *TypeInfer::followFcnPointers(Value *Callee, Location Loc) {
  if (auto FcnTy = followFcnPointer(Callee->getType())) {
    while (auto DeeperFcn = followFcnPointer(FcnTy->getRTy()))
      FcnTy = DeeperFcn;
    return FcnTy;
  }
  std::ostringstream ErrMsg;
  ErrMsg << Callee->getName() << " was expected to be a pointer to a function"
         << " but was instead found to be of type " << *Callee->getType();
  DiagnosticPrinter(Loc) << ErrMsg.str();
  exit(1);
}
Beispiel #9
0
void Resolve::runOnModule(Module *M) {
  K = M->getContext();
  for (auto P : Externals::get(K)->getProtos())
    if (!K->Map.add(P)) {
      auto ErrMsg =
          "prototype " + P->getName() +
          " attempting to overshadow previously bound symbol with same name";
      DiagnosticPrinter(P->getSourceLocation()) << ErrMsg;
      exit(1);
    }
  for (auto &F : *M)
    if (!K->Map.add(F)) {
      DiagnosticPrinter(F->getSourceLocation())
          << "function " + F->getName() + " attempting to overshadow "
                                          "previously bound symbol with same "
                                          "name";
      exit(1);
    }
  for (auto &F : *M)
    runOnFunction(F);
}
Beispiel #10
0
Type *TypeInfer::visit(ReturnInst *V) {
  if (!V->getVal())
    return VoidType::get(K);
  auto Val = V->getVal();
  auto Ty = visit(Val);
  if (isa<VoidType>(Ty)) {
    auto CannotReturnVoid = "cannot return expression of Void type";
    DiagnosticPrinter(Val->getSourceLocation()) << CannotReturnVoid;
    exit(1);
  }
  V->setType(Ty);
  return Ty;
}
Beispiel #11
0
Type *TypeInfer::visit(IfInst *V) {
  auto TrueTy = visit(V->getTrueBB());
  auto FalseTy = visit(V->getFalseBB());
  if (TrueTy != FalseTy) {
    std::ostringstream ErrMsg;
    ErrMsg << "mismatched types: true block is inferred to be of type "
           << *TrueTy << " and false block is inferred to be of type "
           << *FalseTy;
    DiagnosticPrinter(V->getSourceLocation()) << ErrMsg.str();
    exit(1);
  }
  V->setType(TrueTy);
  return TrueTy;
}
Beispiel #12
0
bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (const std::string &Str : CommandLine)
    Argv.push_back(Str.c_str());
  const char *const BinaryName = Argv[0];
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), &*DiagOpts);
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
      DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);

  const std::unique_ptr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem()));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const std::unique_ptr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  // Just print the cc1 options if -### was present.
  if (Compilation->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {
    Compilation->getJobs().Print(llvm::errs(), "\n", true);
    return true;
  }
  // We expect to get back a command job.  If there is no job
  // everything was handled by the driver.
  const driver::JobList &Jobs = Compilation->getJobs();                                   
  if (Jobs.size() == 0)
    return true;                                                                   

  const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (!CC1Args) {
    return false;
  }
  std::unique_ptr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  if(Diagnostics.hasUncompilableErrorOccurred())
    return false;
  // FIXME: remove this when all users have migrated!
  for (const auto &It : MappedFileContents) {
    // Inject the code as the given file name into the preprocessor options.
    std::unique_ptr<llvm::MemoryBuffer> Input =
        llvm::MemoryBuffer::getMemBuffer(It.getValue());
    Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(),
                                                      Input.release());
  }
  return runInvocation(BinaryName, Compilation.get(), Invocation.release(),
                       PCHContainerOps);
}
Beispiel #13
0
void TypeInfer::verifyArity(CallInst *V, FunctionType *Ty) {
  std::vector<Type *> OpTys;
  for (auto Op : V->operands())
    OpTys.push_back(Op->getType());
  auto ATys = Ty->getATys();
  unsigned OpSize = OpTys.size();
  unsigned Arity = ATys.size();
  if (OpSize != Arity) {
    std::ostringstream ErrMsg;
    ErrMsg << "Call expected " << Arity
           << " number of arguments, but has been supplied " << OpSize
           << " arguments";
    DiagnosticPrinter(V->getSourceLocation()) << ErrMsg.str();
    exit(1);
  }
}
Beispiel #14
0
int RefactoringTool::run(FrontendActionFactory *ActionFactory) {
  int Result = Tool.run(ActionFactory);
  LangOptions DefaultLangOptions;
  DiagnosticOptions DefaultDiagnosticOptions;
  TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(),
                                          DefaultDiagnosticOptions);
  DiagnosticsEngine Diagnostics(
      llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
      &DiagnosticPrinter, false);
  SourceManager Sources(Diagnostics, Tool.getFiles());
  Rewriter Rewrite(Sources, DefaultLangOptions);
  if (!applyAllReplacements(Replace, Rewrite)) {
    llvm::errs() << "Skipped some replacements.\n";
  }
  if (!saveRewrittenFiles(Rewrite)) {
    llvm::errs() << "Could not save rewritten files.\n";
    return 1;
  }
  return Result;
}
Beispiel #15
0
int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
  if (int Result = run(ActionFactory)) {
    return Result;
  }

  LangOptions DefaultLangOptions;
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
      &*DiagOpts, &DiagnosticPrinter, false);
  SourceManager Sources(Diagnostics, getFiles());
  Rewriter Rewrite(Sources, DefaultLangOptions);

  if (!applyAllReplacements(Rewrite)) {
    llvm::errs() << "Skipped some replacements.\n";
  }

  return saveRewrittenFiles(Rewrite);
}
Beispiel #16
0
llvm::Function *Prototype::getOrInsert(llvm::Module *M) {
  auto FnTy = cast<llvm::FunctionType>(type()->generate(M));
  auto MangledName = getMangledName();

  /// getOrInsertFunction::
  ///
  /// Look up the specified function in the module symbol table.
  /// Four possibilities:
  /// 1. If it does not exist, add a prototype for the function and return it.
  /// 2. If it exists, and has a local linkage, the existing function is
  /// renamed and a new one is inserted.
  /// 3. Otherwise, if the existing function has the correct prototype, return
  /// the existing function.
  /// 4. Finally, the function exists but has the wrong prototype: return the
  /// function with a constantexpr cast to the right prototype.
  auto Const = M->getOrInsertFunction(MangledName, FnTy);

  if (auto FunctionCandidate = dyn_cast<llvm::Function>(Const))
    return FunctionCandidate;
  auto Error = MangledName + " was declared with different signature earlier";
  DiagnosticPrinter(SourceLoc) << Error;
  exit(1);
}
Beispiel #17
0
 friend ostream &operator<<(ostream &Stream, const Type &T) {
   auto DiagStream = DiagnosticPrinter(Stream);
   T.print(DiagStream);
   return Stream;
 }