blob: c25cce4ab33b303851423c6b031de030c253f6f2 [file] [log] [blame]
//===----- CGCoroutine.cpp - Emit CIR Code for C++ coroutines -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of coroutines.
//
//===----------------------------------------------------------------------===//
#include "CIRGenFunction.h"
#include "mlir/Support/LLVM.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
using namespace clang;
using namespace clang::CIRGen;
struct clang::CIRGen::CGCoroData {
// Stores the __builtin_coro_id emitted in the function so that we can supply
// it as the first argument to other builtins.
cir::CallOp coroId = nullptr;
};
// Defining these here allows to keep CGCoroData private to this file.
CIRGenFunction::CGCoroInfo::CGCoroInfo() {}
CIRGenFunction::CGCoroInfo::~CGCoroInfo() {}
static void createCoroData(CIRGenFunction &cgf,
CIRGenFunction::CGCoroInfo &curCoro,
cir::CallOp coroId) {
assert(!curCoro.data && "EmitCoroutineBodyStatement called twice?");
curCoro.data = std::make_unique<CGCoroData>();
curCoro.data->coroId = coroId;
}
cir::CallOp CIRGenFunction::emitCoroIDBuiltinCall(mlir::Location loc,
mlir::Value nullPtr) {
cir::IntType int32Ty = builder.getUInt32Ty();
const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
unsigned newAlign = ti.getNewAlign() / ti.getCharWidth();
mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroId);
cir::FuncOp fnOp;
if (!builtin) {
fnOp = cgm.createCIRBuiltinFunction(
loc, cgm.builtinCoroId,
cir::FuncType::get({int32Ty, VoidPtrTy, VoidPtrTy, VoidPtrTy}, int32Ty),
/*FD=*/nullptr);
assert(fnOp && "should always succeed");
} else {
fnOp = cast<cir::FuncOp>(builtin);
}
return builder.createCallOp(loc, fnOp,
mlir::ValueRange{builder.getUInt32(newAlign, loc),
nullPtr, nullPtr, nullPtr});
}
mlir::LogicalResult
CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
mlir::Location openCurlyLoc = getLoc(s.getBeginLoc());
cir::ConstantOp nullPtrCst = builder.getNullPtr(VoidPtrTy, openCurlyLoc);
auto fn = mlir::cast<cir::FuncOp>(curFn);
fn.setCoroutine(true);
cir::CallOp coroId = emitCoroIDBuiltinCall(openCurlyLoc, nullPtrCst);
createCoroData(*this, curCoro, coroId);
assert(!cir::MissingFeatures::coroAllocBuiltinCall());
assert(!cir::MissingFeatures::coroBeginBuiltinCall());
assert(!cir::MissingFeatures::generateDebugInfo());
return mlir::success();
}