<commit_before>//===--- IRGen.cpp - Swift LLVM IR Generation -----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the entrypoints into IR generation.
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/IRGen/Options.h"
#include "swift/AST/AST.h"
#include "swift/AST/Diagnostics.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Linker.h"

#include "IRGenModule.h"

using namespace swift;
using namespace irgen;
using namespace llvm;

static bool isBinaryOutput(OutputKind kind) {
  switch (kind) {
  case OutputKind::Module:
  case OutputKind::LLVMAssembly:
  case OutputKind::NativeAssembly:
    return false;
  case OutputKind::LLVMBitcode:
  case OutputKind::ObjectFile:
    return true;
  }
  llvm_unreachable("bad output kind!");
}

static void addSwiftARCOptPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCOptPass());
}

static void addSwiftExpandPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCExpandPass());
}

void swift::performIRGeneration(Options &Opts, llvm::Module *Module,
                                TranslationUnit *TU, unsigned StartElem) {
  assert(!TU->Ctx.hadError());

  std::unique_ptr<LLVMContext> Context;
  std::unique_ptr<llvm::Module> ModuleOwner;
  if (!Module) {
    Context.reset(new LLVMContext);
    ModuleOwner.reset(new llvm::Module(Opts.OutputFilename, *Context));
    Module = ModuleOwner.get();
  }

  Module->setTargetTriple(Opts.Triple);

  std::string Error;
  const Target *Target =
    TargetRegistry::lookupTarget(Opts.Triple, Error);
  if (!Target) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, Error);
    return;
  }

  // The integer values 0-3 map exactly to the values of this enum.
  CodeGenOpt::Level OptLevel = static_cast<CodeGenOpt::Level>(Opts.OptLevel);

  // Set up TargetOptions.
  // Things that maybe we should collect from the command line:
  //   - CPU
  //   - features
  //   - relocation model
  //   - code model
  TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElimNonLeaf = true;
  
  // Create a target machine.
  TargetMachine *TargetMachine
    = Target->createTargetMachine(Opts.Triple, /*cpu*/ "", /*features*/ "",
                                  TargetOpts, Reloc::Default,
                                  CodeModel::Default, OptLevel);
  if (!TargetMachine) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, "no LLVM target machine");
    return;
  }

  // Set the module's string representation.
  const llvm::DataLayout *DataLayout = TargetMachine->getDataLayout();
  assert(DataLayout && "target machine didn't set DatLayout?");
  Module->setDataLayout(DataLayout->getStringRepresentation());

  // Emit the translation unit.
  IRGenModule IRM(TU->Ctx, Opts, *Module, *DataLayout);
  IRM.emitTranslationUnit(TU, StartElem);

  // Bail out if there are any errors.
  if (TU->Ctx.hadError()) return;

  // Ugly standard library optimization hack, part 1: pull in the relevant
  // IR from swift.swift.
  // FIXME: We should pre-generate a swift.bc; it would be substantially
  // faster we could skip both generating and optimizing the standard library.
  // FIXME: Figure out how to get this working for the REPL.
  bool UseStandardLibraryHack = Opts.OptLevel != 0;
  if (UseStandardLibraryHack) {
    for (auto ModPair : TU->getImportedModules()) {
      if (isa<BuiltinModule>(ModPair.second))
        continue;

      TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);

      if (SubTU->Name.str() == "swift") {
        Options SubOpts;
        SubOpts.Triple = Opts.Triple;
        SubOpts.OutputKind = OutputKind::Module;
        SubOpts.OptLevel = 2;
        llvm::Module SubModule(SubTU->Name.str(), Module->getContext());
        performCaptureAnalysis(SubTU);
        performIRGeneration(SubOpts, &SubModule, SubTU);

        for (llvm::Function &F : SubModule)
          if (!F.isDeclaration() && F.hasExternalLinkage())
            F.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
        for (llvm::GlobalVariable &G : SubModule.getGlobalList())
          if (!G.isDeclaration() && G.hasExternalLinkage())
            G.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
        for (llvm::GlobalAlias &A : SubModule.getAliasList())
          if (!A.isDeclaration() && A.hasExternalLinkage())
            A.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);

        std::string ErrorMessage;
        if (llvm::Linker::LinkModules(Module, &SubModule,
                                      llvm::Linker::DestroySource,
                                      &ErrorMessage)) {
          llvm::errs() << "Error linking swift modules\n";
          llvm::errs() << ErrorMessage << "\n";
          return;
        }
      }
    }
  }

  llvm::OwningPtr<raw_fd_ostream> RawOS;
  formatted_raw_ostream FormattedOS;
  if (!Opts.OutputFilename.empty()) {
    // Try to open the output file.  Clobbering an existing file is fine.
    // Open in binary mode if we're doing binary output.
    unsigned OSFlags = 0;
    if (isBinaryOutput(Opts.OutputKind))
      OSFlags |= raw_fd_ostream::F_Binary;
    RawOS.reset(new raw_fd_ostream(Opts.OutputFilename.c_str(),
                                   Error, OSFlags));
    if (RawOS->has_error() || !Error.empty()) {
      TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
                             Opts.OutputFilename, Error);
      RawOS->clear_error();
      return;<commit_msg>Fix my crazy swift.swift inlining hack so it doesn't pull in llvm.global_ctors.  <rdar://problem/12539597>.<commit_after>//===--- IRGen.cpp - Swift LLVM IR Generation -----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the entrypoints into IR generation.
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/IRGen/Options.h"
#include "swift/AST/AST.h"
#include "swift/AST/Diagnostics.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Linker.h"

#include "IRGenModule.h"

using namespace swift;
using namespace irgen;
using namespace llvm;

static bool isBinaryOutput(OutputKind kind) {
  switch (kind) {
  case OutputKind::Module:
  case OutputKind::LLVMAssembly:
  case OutputKind::NativeAssembly:
    return false;
  case OutputKind::LLVMBitcode:
  case OutputKind::ObjectFile:
    return true;
  }
  llvm_unreachable("bad output kind!");
}

static void addSwiftARCOptPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCOptPass());
}

static void addSwiftExpandPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCExpandPass());
}

void swift::performIRGeneration(Options &Opts, llvm::Module *Module,
                                TranslationUnit *TU, unsigned StartElem) {
  assert(!TU->Ctx.hadError());

  std::unique_ptr<LLVMContext> Context;
  std::unique_ptr<llvm::Module> ModuleOwner;
  if (!Module) {
    Context.reset(new LLVMContext);
    ModuleOwner.reset(new llvm::Module(Opts.OutputFilename, *Context));
    Module = ModuleOwner.get();
  }

  Module->setTargetTriple(Opts.Triple);

  std::string Error;
  const Target *Target =
    TargetRegistry::lookupTarget(Opts.Triple, Error);
  if (!Target) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, Error);
    return;
  }

  // The integer values 0-3 map exactly to the values of this enum.
  CodeGenOpt::Level OptLevel = static_cast<CodeGenOpt::Level>(Opts.OptLevel);

  // Set up TargetOptions.
  // Things that maybe we should collect from the command line:
  //   - CPU
  //   - features
  //   - relocation model
  //   - code model
  TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElimNonLeaf = true;
  
  // Create a target machine.
  TargetMachine *TargetMachine
    = Target->createTargetMachine(Opts.Triple, /*cpu*/ "", /*features*/ "",
                                  TargetOpts, Reloc::Default,
                                  CodeModel::Default, OptLevel);
  if (!TargetMachine) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, "no LLVM target machine");
    return;
  }

  // Set the module's string representation.
  const llvm::DataLayout *DataLayout = TargetMachine->getDataLayout();
  assert(DataLayout && "target machine didn't set DatLayout?");
  Module->setDataLayout(DataLayout->getStringRepresentation());

  // Emit the translation unit.
  IRGenModule IRM(TU->Ctx, Opts, *Module, *DataLayout);
  IRM.emitTranslationUnit(TU, StartElem);

  // Bail out if there are any errors.
  if (TU->Ctx.hadError()) return;

  // Ugly standard library optimization hack, part 1: pull in the relevant
  // IR from swift.swift.
  // FIXME: We should pre-generate a swift.bc; it would be substantially
  // faster we could skip both generating and optimizing the standard library.
  // FIXME: Figure out how to get this working for the REPL.
  bool UseStandardLibraryHack = Opts.OptLevel != 0;
  if (UseStandardLibraryHack) {
    for (auto ModPair : TU->getImportedModules()) {
      if (isa<BuiltinModule>(ModPair.second))
        continue;

      TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);

      if (SubTU->Name.str() == "swift") {
        Options SubOpts;
        SubOpts.Triple = Opts.Triple;
        SubOpts.OutputKind = OutputKind::Module;
        SubOpts.OptLevel = 2;
        llvm::Module SubModule(SubTU->Name.str(), Module->getContext());
        performCaptureAnalysis(SubTU);
        performIRGeneration(SubOpts, &SubModule, SubTU);

        SmallVector<GlobalValue*, 8> DeclsToErase;
        for (llvm::Function &F : SubModule)
          if (!F.isDeclaration() && F.hasExternalLinkage())
            F.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
        for (llvm::GlobalVariable &G : SubModule.getGlobalList()) {
          if (!G.isDeclaration() && G.hasExternalLinkage())
            G.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
          if (G.hasAppendingLinkage())
            DeclsToErase.push_back(&G);
        }
        for (llvm::GlobalAlias &A : SubModule.getAliasList())
          if (!A.isDeclaration() && A.hasExternalLinkage())
            A.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);

        for (auto G : DeclsToErase)
          G->eraseFromParent();

        std::string ErrorMessage;
        if (llvm::Linker::LinkModules(Module, &SubModule,
                                      llvm::Linker::DestroySource,
                                      &ErrorMessage)) {
          llvm::errs() << "Error linking swift modules\n";
          llvm::errs() << ErrorMessage << "\n";
          return;
        }
      }
    }
  }

  llvm::OwningPtr<raw_fd_ostream> RawOS;
  formatted_raw_ostream FormattedOS;
  if (!Opts.OutputFilename.empty()) {
    // Try to open the output file.  Clobbering an existing file is fine.
    // Open in binary mode if we're doing binary output.
    unsigned OSFlags = 0;
    if (isBinaryOutput(Opts.OutputKind))
      OSFlags |= raw_fd_ostream::F_Binary;
    RawOS.reset(new raw_fd_ostream(Opts.OutputFilename.c_str(),
                                   Error, OSFlags));
    if (RawOS->has_error() || !Error.empty()) {
      TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
                             Opts.OutputFilename, Error);
      RawOS->clear_error();
      return;
{'fraction_non_alphanumeric': 0.1475662579839953, 'fraction_numerical': 0.0033037221936715365, 'mean_word_length': 2.702636586028812, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6231343', 'n_tokens_mistral': 4072, 'n_tokens_neox': 3955, 'n_words': 930}