@@ -178,6 +178,140 @@ void SILGenModule::emitEntryPoint(SourceFile *SF, SILFunction *TopLevel) {
178178 emitLazyConformancesForFunction (&toplevel);
179179}
180180
181+ // / Generate code for calling the given main function.
182+ void SILGenFunction::emitCallToMain (FuncDecl *mainFunc) {
183+ // This function is effectively emitting SIL for:
184+ // return try await TheType.$main();
185+ auto loc = SILLocation (mainFunc);
186+ auto *entryBlock = B.getInsertionBB ();
187+
188+ SILDeclRef mainFunctionDeclRef (mainFunc, SILDeclRef::Kind::Func);
189+ SILFunction *mainFunction =
190+ SGM.getFunction (mainFunctionDeclRef, NotForDefinition);
191+
192+ NominalTypeDecl *mainType =
193+ mainFunc->getDeclContext ()->getSelfNominalTypeDecl ();
194+ auto metatype = B.createMetatype (mainType, getLoweredType (mainType->getInterfaceType ()));
195+
196+ auto mainFunctionRef = B.createFunctionRef (loc, mainFunction);
197+
198+ auto builtinInt32Type = SILType::getBuiltinIntegerType (
199+ 32 , getASTContext ());
200+
201+ // Set up the exit block, which will either return the exit value
202+ // (for synchronous main()) or call exit() with the return value (for
203+ // asynchronous main()).
204+ auto *exitBlock = createBasicBlock ();
205+ SILValue exitCode =
206+ exitBlock->createPhiArgument (builtinInt32Type, OwnershipKind::None);
207+ B.setInsertionPoint (exitBlock);
208+
209+ if (!mainFunc->hasAsync ()) {
210+ auto returnType = F.getConventions ().getSingleSILResultType (
211+ B.getTypeExpansionContext ());
212+ if (exitCode->getType () != returnType)
213+ exitCode = B.createStruct (loc, returnType, exitCode);
214+ B.createReturn (loc, exitCode);
215+ } else {
216+ FuncDecl *exitFuncDecl = SGM.getExit ();
217+ assert (exitFuncDecl && " Failed to find exit function declaration" );
218+ SILFunction *exitSILFunc = SGM.getFunction (
219+ SILDeclRef (exitFuncDecl, SILDeclRef::Kind::Func, /* isForeign*/ true ),
220+ NotForDefinition);
221+
222+ SILFunctionType &funcType =
223+ *exitSILFunc->getLoweredType ().getAs <SILFunctionType>();
224+ SILType retType = SILType::getPrimitiveObjectType (
225+ funcType.getParameters ().front ().getInterfaceType ());
226+ exitCode = B.createStruct (loc, retType, exitCode);
227+ SILValue exitCall = B.createFunctionRef (loc, exitSILFunc);
228+ B.createApply (loc, exitCall, {}, {exitCode});
229+ B.createUnreachable (loc);
230+ }
231+
232+ // Form a call to the main function.
233+ CanSILFunctionType mainFnType = mainFunction->getConventions ().funcTy ;
234+ ASTContext &ctx = getASTContext ();
235+ if (mainFnType->hasErrorResult ()) {
236+ auto *successBlock = createBasicBlock ();
237+ B.setInsertionPoint (successBlock);
238+ successBlock->createPhiArgument (SGM.Types .getEmptyTupleType (),
239+ OwnershipKind::None);
240+ SILValue zeroReturnValue =
241+ B.createIntegerLiteral (loc, builtinInt32Type, 0 );
242+ B.createBranch (loc, exitBlock, {zeroReturnValue});
243+
244+ SILResultInfo errorResult = mainFnType->getErrorResult ();
245+ SILType errorType = errorResult.getSILStorageInterfaceType ();
246+
247+ auto *failureBlock = createBasicBlock ();
248+ B.setInsertionPoint (failureBlock);
249+ SILValue error;
250+ if (IndirectErrorResult) {
251+ error = IndirectErrorResult;
252+ } else {
253+ error = failureBlock->createPhiArgument (
254+ errorType, OwnershipKind::Owned);
255+ }
256+
257+ // Log the error.
258+ if (errorType.getASTType ()->isErrorExistentialType ()) {
259+ // Load the indirect error, if needed.
260+ if (IndirectErrorResult) {
261+ const TypeLowering &errorExistentialTL = getTypeLowering (errorType);
262+
263+ error = emitLoad (
264+ loc, IndirectErrorResult, errorExistentialTL, SGFContext (),
265+ IsTake).forward (*this );
266+ }
267+
268+ // Call the errorInMain entrypoint, which takes an existential
269+ // error.
270+ B.createBuiltin (loc, ctx.getIdentifier (" errorInMain" ),
271+ SGM.Types .getEmptyTupleType (), {}, {error});
272+ } else {
273+ // Call the _errorInMainTyped entrypoint, which handles
274+ // arbitrary error types.
275+ SILValue tmpBuffer;
276+
277+ FuncDecl *entrypoint = ctx.getErrorInMainTyped ();
278+ auto genericSig = entrypoint->getGenericSignature ();
279+ SubstitutionMap subMap = SubstitutionMap::get (
280+ genericSig, [&](SubstitutableType *dependentType) {
281+ return errorType.getASTType ();
282+ }, LookUpConformanceInModule (getModule ().getSwiftModule ()));
283+
284+ // Generic errors are passed indirectly.
285+ if (!error->getType ().isAddress ()) {
286+ auto *tmp = B.createAllocStack (loc,
287+ error->getType ().getObjectType (),
288+ llvm::None);
289+ emitSemanticStore (
290+ loc, error, tmp,
291+ getTypeLowering (tmp->getType ()), IsInitialization);
292+ tmpBuffer = tmp;
293+ error = tmp;
294+ }
295+
296+ emitApplyOfLibraryIntrinsic (
297+ loc, entrypoint, subMap,
298+ { ManagedValue::forForwardedRValue (*this , error) },
299+ SGFContext ());
300+ }
301+ B.createUnreachable (loc);
302+
303+ B.setInsertionPoint (entryBlock);
304+ B.createTryApply (loc, mainFunctionRef, SubstitutionMap (),
305+ {metatype}, successBlock, failureBlock);
306+ } else {
307+ B.setInsertionPoint (entryBlock);
308+ B.createApply (loc, mainFunctionRef, SubstitutionMap (), {metatype});
309+ SILValue returnValue =
310+ B.createIntegerLiteral (loc, builtinInt32Type, 0 );
311+ B.createBranch (loc, exitBlock, {returnValue});
312+ }
313+ }
314+
181315void SILGenModule::emitEntryPoint (SourceFile *SF) {
182316 assert (!M.lookUpFunction (getASTContext ().getEntryPointFunctionName ()) &&
183317 " already emitted toplevel?!" );
0 commit comments