xref: /llvm-project/flang/lib/Optimizer/Builder/Runtime/Main.cpp (revision ab1ee912be95a864827aadd33175bfeec026f000)
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 
21 using namespace Fortran::runtime;
22 
23 /// Create a `int main(...)` that calls the Fortran entry point
24 void 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