<commit_before>
var _            = require('lodash'),
    AST          = require('../ast'),
    types        = require('../types'),
    scope        = require('../typesystem/scope'),
    Scope        = scope.Scope,
    ClosingScope = scope.ClosingScope,
    LLVM         = require('./llvm/library'),
    Builtins     = require('./llvm/builtins'),
    slots        = require('./llvm/slots'),
    Errors       = require('../errors'),
    ICE          = Errors.InternalCompilerError,
    // Target information and setup
    target       = require('./llvm/target'),
    util         = require('./llvm/util'),
    BinaryOps    = require('./llvm/binary-ops')

var isLastInstructionTerminator = util.isLastInstructionTerminator,
    compileTruthyTest           = util.compileTruthyTest,
    assertInstanceOf            = util.assertInstanceOf

var NativeFunction    = require('./llvm/native-function'),
    NativeObject      = require('./llvm/native-object'),
    nativeTypeForType = require('./llvm/native-types').nativeTypeForType

// Unbox the slots module
var Slots         = slots.Slots,
    ConstantSlots = slots.ConstantSlots,
    GlobalSlots   = slots.GlobalSlots

var Int1Type    = LLVM.Types.Int1Type,
    Int8Type    = LLVM.Types.Int8Type,
    Int32Type   = LLVM.Types.Int32Type,
    Int64Type   = LLVM.Types.Int64Type,
    VoidType    = LLVM.Types.VoidType,
    Int8PtrType = LLVM.Types.pointerType(LLVM.Types.Int8Type)

var Int32Zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)

// LLVM library functions we'll be using
var TypeOf            = LLVM.Library.LLVMTypeOf,
    GetTypeKind       = LLVM.Library.LLVMGetTypeKind,
    DumpType          = function (ty) { LLVM.Library.LLVMDumpType(ty); console.log('') },
    PrintTypeToString = LLVM.Library.LLVMPrintTypeToString,
    GetParam          = LLVM.Library.LLVMGetParam,
    PointerTypeKind   = GetTypeKind(Int8PtrType)


function Context () {
  // Externally linked functions
  this.extern = {}
  // Globals
  this.globals = {}
}
Context.prototype.addGlobal = function (name, type) {
  assertInstanceOf(type, Buffer)
  var global = LLVM.Library.LLVMAddGlobal(this.module.ptr, type, name)
  this.globals[name] = global
  return global
}
Context.prototype.getGlobal = function (name) {
  if (!this.hasGlobal(name)) { throw new Error('Global definition not found: '+name) }
  return this.globals[name]
}
Context.prototype.hasGlobal = function (name) {
  return (this.globals[name] ? true : false)
}
Context.prototype.buildGlobalLoad = function (name) {
  var global = this.globals[name],
      // ptr = this.builder.buildGEP(global, [Int32Zero], name),
      val    = this.builder.buildLoad(global, name)
  return val
}


function BlockContext (ctx, parentFn, block, slots) {
  this.ctx   = ctx
  this.fn    = parentFn
  this.block = block
  this.slots = slots
}

function BasicLogger () {
  this.info = console.log
}


function unboxInstanceType (instance, expectedType) {
  assertInstanceOf(instance, types.Instance)
  var type = instance.type
  if (expectedType !== undefined) {
    assertInstanceOf(type, expectedType)
  }
  return type
}

var StaticPassManager = null
function getStaticPassManager () {
  if (StaticPassManager) { return StaticPassManager }

  // Setup the pass manager and optimization passes
  var pm = LLVM.Library.LLVMCreatePassManager()
  // Global value numbering
  LLVM.Library.LLVMAddGVNPass(pm)
  // Convert aggregate stack allocations into SSA registers
  LLVM.Library.LLVMAddScalarReplAggregatesPass(pm)
  // Promote by-reference arguments to scalar
  LLVM.Library.LLVMAddArgumentPromotionPass(pm)
  // Convert load-stores on stack allocated slots to phi nodes
  LLVM.Library.LLVMAddPromoteMemoryToRegisterPass(pm)
  // Merge duplicate global constants
  LLVM.Library.LLVMAddConstantMergePass(pm)
  // Turns induction variables (ie. in loops) into simpler forms for easier
  // later analysis
  LLVM.Library.LLVMAddIndVarSimplifyPass(pm)
  // Simple dead code elimination and basic-block merging
  //   http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg
  LLVM.Library.LLVMAddCFGSimplificationPass(pm)
  // Save the pass manager and return it
  StaticPassManager = pm
  return pm
}

AST.Node.prototype.compileToValue = function () {
  throw new Error('Compilation to value not yet implemented for: '+this.constructor.name)
}

AST.Root.prototype.emitToFile = function (opts) {
  if (opts.module) {
    assertInstanceOf(opts.module, types.Module)
  }
  var ctx = new Context()
  ctx.isMain       = (opts.module ? true : false)
  ctx.targetModule = (opts.module ? opts.module : null)
  ctx.module       = new LLVM.Module(ctx.targetModule ? ctx.targetModule.getNativeName() : 'main')
  ctx.builder      = new LLVM.Builder()
  ctx.funcs        = {}
  // Slots for global values (eg. builtins)
  ctx.globalSlots  = new GlobalSlots()
  // Maps sets of Slots to their associated Scope by the scope's ID
  ctx.slotsMap     = {}
  // Configuration options
  ctx.castValuePointers   = false
  ctx.noCastValuePointers = !ctx.castValuePointers
  ctx.logger              = (opts.logger ? opts.logger : (new BasicLogger()))
  // List of output bitcode files built
  ctx.outputs = (opts.outputs ? opts.outputs : [])
  // Add ourselves to that list
  var outFile = bitcodeFileForSourceFile(this.file.path)
  ctx.outputs.push(outFile)

  var mainType = new LLVM.FunctionType(Int32Type, [], false),
      mainFunc = null
  if (ctx.isMain) {
    var initName = ctx.targetModule.getNativeName()+'_init'
    mainFunc = ctx.module.addFunction(initName, mainType)
  } else {
    // Set up the main function
    mainFunc = ctx.module.addFunction('main', mainType)
    // Also setup information about our compilation target
    target.initializeTarget(ctx)
  }
  var mainEntry = mainFunc.appendBasicBlock('entry')

  // Add the root scope to the slots map
  var rootScope = this.scope.parent
  if (!rootScope.isRoot) { throw new Error("Couldn't find root scope") }
  ctx.slotsMap[rootScope.id] = ctx.globalSlots

  // Add the builtins
  Builtins.compile(ctx, mainEntry, this)
  BinaryOps.initialize(ctx, rootScope)

  // Setup the entry into the function
  ctx.builder.positionAtEnd(mainEntry)
  if (ctx.isMain === true) {
    // Initialize the GC
    ctx.builder.buildCall(ctx.extern.GC_init, [], '')
  }

  // Compile ourselves in the main entry function
  this.buildMain(ctx, mainFunc, mainEntry)

  // Run the optimization passes
  LLVM.Library.LLVMRunPassManager(getStaticPassManager(), ctx.module.ptr)
 
  // ctx.module.dump()<commit_msg>Bugfix in detection of main modules<commit_after>
var _            = require('lodash'),
    AST          = require('../ast'),
    types        = require('../types'),
    scope        = require('../typesystem/scope'),
    Scope        = scope.Scope,
    ClosingScope = scope.ClosingScope,
    LLVM         = require('./llvm/library'),
    Builtins     = require('./llvm/builtins'),
    slots        = require('./llvm/slots'),
    Errors       = require('../errors'),
    ICE          = Errors.InternalCompilerError,
    // Target information and setup
    target       = require('./llvm/target'),
    util         = require('./llvm/util'),
    BinaryOps    = require('./llvm/binary-ops')

var isLastInstructionTerminator = util.isLastInstructionTerminator,
    compileTruthyTest           = util.compileTruthyTest,
    assertInstanceOf            = util.assertInstanceOf

var NativeFunction    = require('./llvm/native-function'),
    NativeObject      = require('./llvm/native-object'),
    nativeTypeForType = require('./llvm/native-types').nativeTypeForType

// Unbox the slots module
var Slots         = slots.Slots,
    ConstantSlots = slots.ConstantSlots,
    GlobalSlots   = slots.GlobalSlots

var Int1Type    = LLVM.Types.Int1Type,
    Int8Type    = LLVM.Types.Int8Type,
    Int32Type   = LLVM.Types.Int32Type,
    Int64Type   = LLVM.Types.Int64Type,
    VoidType    = LLVM.Types.VoidType,
    Int8PtrType = LLVM.Types.pointerType(LLVM.Types.Int8Type)

var Int32Zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)

// LLVM library functions we'll be using
var TypeOf            = LLVM.Library.LLVMTypeOf,
    GetTypeKind       = LLVM.Library.LLVMGetTypeKind,
    DumpType          = function (ty) { LLVM.Library.LLVMDumpType(ty); console.log('') },
    PrintTypeToString = LLVM.Library.LLVMPrintTypeToString,
    GetParam          = LLVM.Library.LLVMGetParam,
    PointerTypeKind   = GetTypeKind(Int8PtrType)


function Context () {
  // Externally linked functions
  this.extern = {}
  // Globals
  this.globals = {}
}
Context.prototype.addGlobal = function (name, type) {
  assertInstanceOf(type, Buffer)
  var global = LLVM.Library.LLVMAddGlobal(this.module.ptr, type, name)
  this.globals[name] = global
  return global
}
Context.prototype.getGlobal = function (name) {
  if (!this.hasGlobal(name)) { throw new Error('Global definition not found: '+name) }
  return this.globals[name]
}
Context.prototype.hasGlobal = function (name) {
  return (this.globals[name] ? true : false)
}
Context.prototype.buildGlobalLoad = function (name) {
  var global = this.globals[name],
      // ptr = this.builder.buildGEP(global, [Int32Zero], name),
      val    = this.builder.buildLoad(global, name)
  return val
}


function BlockContext (ctx, parentFn, block, slots) {
  this.ctx   = ctx
  this.fn    = parentFn
  this.block = block
  this.slots = slots
}

function BasicLogger () {
  this.info = console.log
}


function unboxInstanceType (instance, expectedType) {
  assertInstanceOf(instance, types.Instance)
  var type = instance.type
  if (expectedType !== undefined) {
    assertInstanceOf(type, expectedType)
  }
  return type
}

var StaticPassManager = null
function getStaticPassManager () {
  if (StaticPassManager) { return StaticPassManager }

  // Setup the pass manager and optimization passes
  var pm = LLVM.Library.LLVMCreatePassManager()
  // Global value numbering
  LLVM.Library.LLVMAddGVNPass(pm)
  // Convert aggregate stack allocations into SSA registers
  LLVM.Library.LLVMAddScalarReplAggregatesPass(pm)
  // Promote by-reference arguments to scalar
  LLVM.Library.LLVMAddArgumentPromotionPass(pm)
  // Convert load-stores on stack allocated slots to phi nodes
  LLVM.Library.LLVMAddPromoteMemoryToRegisterPass(pm)
  // Merge duplicate global constants
  LLVM.Library.LLVMAddConstantMergePass(pm)
  // Turns induction variables (ie. in loops) into simpler forms for easier
  // later analysis
  LLVM.Library.LLVMAddIndVarSimplifyPass(pm)
  // Simple dead code elimination and basic-block merging
  //   http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg
  LLVM.Library.LLVMAddCFGSimplificationPass(pm)
  // Save the pass manager and return it
  StaticPassManager = pm
  return pm
}

AST.Node.prototype.compileToValue = function () {
  throw new Error('Compilation to value not yet implemented for: '+this.constructor.name)
}

AST.Root.prototype.emitToFile = function (opts) {
  if (opts.module) {
    assertInstanceOf(opts.module, types.Module)
  }
  var ctx = new Context()
  ctx.isMain       = (opts.module ? false : true)
  ctx.targetModule = (opts.module ? opts.module : null)
  ctx.module       = new LLVM.Module(ctx.targetModule ? ctx.targetModule.getNativeName() : 'main')
  ctx.builder      = new LLVM.Builder()
  ctx.funcs        = {}
  // Slots for global values (eg. builtins)
  ctx.globalSlots  = new GlobalSlots()
  // Maps sets of Slots to their associated Scope by the scope's ID
  ctx.slotsMap     = {}
  // Configuration options
  ctx.castValuePointers   = false
  ctx.noCastValuePointers = !ctx.castValuePointers
  ctx.logger              = (opts.logger ? opts.logger : (new BasicLogger()))
  // List of output bitcode files built
  ctx.outputs = (opts.outputs ? opts.outputs : [])
  // Add ourselves to that list
  var outFile = bitcodeFileForSourceFile(this.file.path)
  ctx.outputs.push(outFile)

  var mainType = new LLVM.FunctionType(Int32Type, [], false),
      mainFunc = null
  if (ctx.isMain) {
    // Set up the main function
    mainFunc = ctx.module.addFunction('main', mainType)
    // Also setup information about our compilation target
    target.initializeTarget(ctx)
  } else {
    var initName = ctx.targetModule.getNativeName()+'_init'
    mainFunc = ctx.module.addFunction(initName, mainType)
  }
  var mainEntry = mainFunc.appendBasicBlock('entry')

  // Add the root scope to the slots map
  var rootScope = this.scope.parent
  if (!rootScope.isRoot) { throw new Error("Couldn't find root scope") }
  ctx.slotsMap[rootScope.id] = ctx.globalSlots

  // Add the builtins
  Builtins.compile(ctx, mainEntry, this)
  BinaryOps.initialize(ctx, rootScope)

  // Setup the entry into the function
  ctx.builder.positionAtEnd(mainEntry)
  if (ctx.isMain === true) {
    // Initialize the GC
    ctx.builder.buildCall(ctx.extern.GC_init, [], '')
  }

  // Compile ourselves in the main entry function
  this.buildMain(ctx, mainFunc, mainEntry)

  // Run the optimization passes
  LLVM.Library.LLVMRunPassManager(getStaticPassManager(), ctx.module.ptr)
 
  // ctx.module.dump()
{'fraction_non_alphanumeric': 0.11235267105464565, 'fraction_numerical': 0.003673656819225471, 'mean_word_length': 3.2702614379084967, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '615862', 'n_tokens_mistral': 4102, 'n_tokens_neox': 4014, 'n_words': 930}