aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Optimizer/Builder/Runtime/Main.cpp
blob: 9ce5e172f3cd39e553ae3f16247f3a9d4d373f3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//===-- Main.cpp - generate main runtime API calls --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "flang/Optimizer/Builder/Runtime/Main.h"
#include "flang/Lower/EnvironmentDefault.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
#include "flang/Runtime/CUDA/init.h"
#include "flang/Runtime/main.h"
#include "flang/Runtime/stop.h"

using namespace Fortran::runtime;

/// Create a `int main(...)` that calls the Fortran entry point
void fir::runtime::genMain(
    fir::FirOpBuilder &builder, mlir::Location loc,
    const std::vector<Fortran::lower::EnvironmentDefault> &defs, bool initCuda,
    bool initCoarrayEnv) {
  auto *context = builder.getContext();
  auto argcTy = builder.getDefaultIntegerType();
  auto ptrTy = mlir::LLVM::LLVMPointerType::get(context);

  // void ProgramStart(int argc, char** argv, char** envp,
  //                   _QQEnvironmentDefaults* env)
  auto startFn = builder.createFunction(
      loc, RTNAME_STRING(ProgramStart),
      mlir::FunctionType::get(context, {argcTy, ptrTy, ptrTy, ptrTy}, {}));
  // void ProgramStop()
  auto stopFn =
      builder.createFunction(loc, RTNAME_STRING(ProgramEndStatement),
                             mlir::FunctionType::get(context, {}, {}));

  // int main(int argc, char** argv, char** envp)
  auto mainFn = builder.createFunction(
      loc, "main",
      mlir::FunctionType::get(context, {argcTy, ptrTy, ptrTy}, argcTy));
  // void _QQmain()
  auto qqMainFn = builder.createFunction(
      loc, "_QQmain", mlir::FunctionType::get(context, {}, {}));

  mainFn.setPublic();

  auto *block = mainFn.addEntryBlock();
  mlir::OpBuilder::InsertionGuard insertGuard(builder);
  builder.setInsertionPointToStart(block);

  // Create the list of any environment defaults for the runtime to set. The
  // runtime default list is only created if there is a main program to ensure
  // it only happens once and to provide consistent results if multiple files
  // are compiled separately.
  auto env = fir::runtime::genEnvironmentDefaults(builder, loc, defs);

  llvm::SmallVector<mlir::Value, 4> args(block->getArguments());
  args.push_back(env);

  fir::CallOp::create(builder, loc, startFn, args);

  if (initCuda) {
    auto initFn = builder.createFunction(
        loc, RTNAME_STRING(CUFInit), mlir::FunctionType::get(context, {}, {}));
    fir::CallOp::create(builder, loc, initFn);
  }
  if (initCoarrayEnv)
    mif::InitOp::create(builder, loc);

  fir::CallOp::create(builder, loc, qqMainFn);
  fir::CallOp::create(builder, loc, stopFn);

  mlir::Value ret = builder.createIntegerConstant(loc, argcTy, 0);
  mlir::func::ReturnOp::create(builder, loc, ret);
}