#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
#include "mlir/Dialect/Async/IR/Async.h"
+#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Dialect/StandardOps/Transforms/FuncConversions.h"
}
//===----------------------------------------------------------------------===//
-// Add malloc/free declarations to the module.
-//===----------------------------------------------------------------------===//
-
-static constexpr const char *kMalloc = "malloc";
-static constexpr const char *kFree = "free";
-
-static void addLLVMFuncDecl(ModuleOp module, ImplicitLocOpBuilder &builder,
- StringRef name, Type ret, ArrayRef<Type> params) {
- if (module.lookupSymbol(name))
- return;
- Type type = LLVM::LLVMFunctionType::get(ret, params);
- builder.create<LLVM::LLVMFuncOp>(name, type);
-}
-
-/// Adds malloc/free declarations to the module.
-static void addCRuntimeDeclarations(ModuleOp module) {
- using namespace mlir::LLVM;
-
- MLIRContext *ctx = module.getContext();
- auto builder =
- ImplicitLocOpBuilder::atBlockEnd(module.getLoc(), module.getBody());
-
- auto voidTy = LLVMVoidType::get(ctx);
- auto i64 = IntegerType::get(ctx, 64);
- auto i8Ptr = LLVMPointerType::get(IntegerType::get(ctx, 8));
-
- addLLVMFuncDecl(module, builder, kMalloc, i8Ptr, {i64});
- addLLVMFuncDecl(module, builder, kFree, voidTy, {i8Ptr});
-}
-
-//===----------------------------------------------------------------------===//
// Coroutine resume function wrapper.
//===----------------------------------------------------------------------===//
// Get coroutine frame size: @llvm.coro.size.i64.
auto coroSize =
rewriter.create<LLVM::CoroSizeOp>(loc, rewriter.getI64Type());
+ // The coroutine lowering doesn't properly account for alignment of the
+ // frame, so align everything to 64 bytes which ought to be enough for
+ // everyone. https://llvm.org/PR53148
+ auto coroAlign = rewriter.create<LLVM::ConstantOp>(
+ op->getLoc(), rewriter.getI64Type(), rewriter.getI64IntegerAttr(64));
// Allocate memory for the coroutine frame.
+ auto allocFuncOp = LLVM::lookupOrCreateAlignedAllocFn(
+ op->getParentOfType<ModuleOp>(), rewriter.getI64Type());
auto coroAlloc = rewriter.create<LLVM::CallOp>(
- loc, i8Ptr, SymbolRefAttr::get(rewriter.getContext(), kMalloc),
- ValueRange(coroSize.getResult()));
+ loc, i8Ptr, SymbolRefAttr::get(allocFuncOp),
+ ValueRange{coroAlign, coroSize.getResult()});
// Begin a coroutine: @llvm.coro.begin.
auto coroId = CoroBeginOpAdaptor(adaptor.getOperands()).id();
rewriter.create<LLVM::CoroFreeOp>(loc, i8Ptr, adaptor.getOperands());
// Free the memory.
- rewriter.replaceOpWithNewOp<LLVM::CallOp>(
- op, TypeRange(), SymbolRefAttr::get(rewriter.getContext(), kFree),
- ValueRange(coroMem.getResult()));
+ auto freeFuncOp =
+ LLVM::lookupOrCreateFreeFn(op->getParentOfType<ModuleOp>());
+ rewriter.replaceOpWithNewOp<LLVM::CallOp>(op, TypeRange(),
+ SymbolRefAttr::get(freeFuncOp),
+ ValueRange(coroMem.getResult()));
return success();
}
// We delay adding the resume function until it's needed because it currently
// fails to compile unless '-O0' is specified.
addAsyncRuntimeApiDeclarations(module);
- addCRuntimeDeclarations(module);
// Lower async.runtime and async.coro operations to Async Runtime API and
// LLVM coroutine intrinsics.