1//===-- Main.cpp - generate main runtime API calls --------------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "flang/Optimizer/Builder/Runtime/Main.h"
10#include "flang/Lower/EnvironmentDefault.h"
11#include "flang/Optimizer/Builder/BoxValue.h"
12#include "flang/Optimizer/Builder/FIRBuilder.h"
13#include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
14#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
15#include "flang/Optimizer/Dialect/FIROps.h"
16#include "flang/Optimizer/Dialect/FIRType.h"
17#include "flang/Runtime/CUDA/init.h"
18#include "flang/Runtime/main.h"
19#include "flang/Runtime/stop.h"
20
21using namespace Fortran::runtime;
22
23/// Create a `int main(...)` that calls the Fortran entry point
24void fir::runtime::genMain(
25 fir::FirOpBuilder &builder, mlir::Location loc,
26 const std::vector<Fortran::lower::EnvironmentDefault> &defs,
27 bool initCuda) {
28 auto *context = builder.getContext();
29 auto argcTy = builder.getDefaultIntegerType();
30 auto ptrTy = mlir::LLVM::LLVMPointerType::get(context);
31
32 // void ProgramStart(int argc, char** argv, char** envp,
33 // _QQEnvironmentDefaults* env)
34 auto startFn = builder.createFunction(
35 loc, RTNAME_STRING(ProgramStart),
36 mlir::FunctionType::get(context, {argcTy, ptrTy, ptrTy, ptrTy}, {}));
37 // void ProgramStop()
38 auto stopFn =
39 builder.createFunction(loc, RTNAME_STRING(ProgramEndStatement),
40 mlir::FunctionType::get(context, {}, {}));
41
42 // int main(int argc, char** argv, char** envp)
43 auto mainFn = builder.createFunction(
44 loc, "main",
45 mlir::FunctionType::get(context, {argcTy, ptrTy, ptrTy}, argcTy));
46 // void _QQmain()
47 auto qqMainFn = builder.createFunction(
48 loc, "_QQmain", mlir::FunctionType::get(context, {}, {}));
49
50 mainFn.setPublic();
51
52 auto *block = mainFn.addEntryBlock();
53 mlir::OpBuilder::InsertionGuard insertGuard(builder);
54 builder.setInsertionPointToStart(block);
55
56 // Create the list of any environment defaults for the runtime to set. The
57 // runtime default list is only created if there is a main program to ensure
58 // it only happens once and to provide consistent results if multiple files
59 // are compiled separately.
60 auto env = fir::runtime::genEnvironmentDefaults(builder, loc, defs);
61
62 llvm::SmallVector<mlir::Value, 4> args(block->getArguments());
63 args.push_back(env);
64
65 builder.create<fir::CallOp>(loc, startFn, args);
66
67 if (initCuda) {
68 auto initFn = builder.createFunction(
69 loc, RTNAME_STRING(CUFInit), mlir::FunctionType::get(context, {}, {}));
70 builder.create<fir::CallOp>(loc, initFn);
71 }
72
73 builder.create<fir::CallOp>(loc, qqMainFn);
74 builder.create<fir::CallOp>(loc, stopFn);
75
76 mlir::Value ret = builder.createIntegerConstant(loc, argcTy, 0);
77 builder.create<mlir::func::ReturnOp>(loc, ret);
78}
79

source code of flang/lib/Optimizer/Builder/Runtime/Main.cpp