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 | |