Skip to content

Commit

Permalink
Revert "[CIR] Remove the !cir.void return type for functions returnin…
Browse files Browse the repository at this point in the history
…g void (llvm#1203)"

This reverts commit 568b515.
  • Loading branch information
keryell committed Dec 19, 2024
1 parent 363440c commit aa71766
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 211 deletions.
13 changes: 5 additions & 8 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -3474,6 +3474,8 @@ def FuncOp : CIR_Op<"func", [
/// Returns the results types that the callable region produces when
/// executed.
llvm::ArrayRef<mlir::Type> getCallableResults() {
if (::llvm::isa<cir::VoidType>(getFunctionType().getReturnType()))
return {};
return getFunctionType().getReturnTypes();
}

Expand All @@ -3490,15 +3492,10 @@ def FuncOp : CIR_Op<"func", [
}

/// Returns the argument types of this function.
llvm::ArrayRef<mlir::Type> getArgumentTypes() {
return getFunctionType().getInputs();
}
llvm::ArrayRef<mlir::Type> getArgumentTypes() { return getFunctionType().getInputs(); }

/// Returns 0 or 1 result type of this function (0 in the case of a function
/// returing void)
llvm::ArrayRef<mlir::Type> getResultTypes() {
return getFunctionType().getReturnTypes();
}
/// Returns the result types of this function.
llvm::ArrayRef<mlir::Type> getResultTypes() { return getFunctionType().getReturnTypes(); }

/// Hook for OpTrait::FunctionOpInterfaceTrait, called after verifying that
/// the 'type' attribute is present and checks if it holds a function type.
Expand Down
19 changes: 7 additions & 12 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -409,27 +409,22 @@ def CIR_FuncType : CIR_Type<"Func", "func"> {

```mlir
!cir.func<!bool ()>
!cir.func<!cir.void ()>
!cir.func<!s32i (!s8i, !s8i)>
!cir.func<!s32i (!s32i, ...)>
```
}];

let parameters = (ins ArrayRefParameter<"mlir::Type">:$inputs, ArrayRefParameter<"mlir::Type">:$returnTypes,
let parameters = (ins ArrayRefParameter<"mlir::Type">:$inputs, "mlir::Type":$returnType,
"bool":$varArg);
let assemblyFormat = [{
`<` custom<FuncType>($returnTypes, $inputs, $varArg) `>`
`<` $returnType ` ` `(` custom<FuncTypeArgs>($inputs, $varArg) `>`
}];

let builders = [
// Construct with an actual return type or explicit !cir.void
TypeBuilderWithInferredContext<(ins
"llvm::ArrayRef<mlir::Type>":$inputs, "mlir::Type":$returnType,
CArg<"bool", "false">:$isVarArg), [{
return $_get(returnType.getContext(), inputs,
::mlir::isa<::cir::VoidType>(returnType) ? llvm::ArrayRef<mlir::Type>{}
: llvm::ArrayRef{returnType},
isVarArg);
return $_get(returnType.getContext(), inputs, returnType, isVarArg);
}]>
];

Expand All @@ -443,11 +438,11 @@ def CIR_FuncType : CIR_Type<"Func", "func"> {
/// Returns the number of arguments to the function.
unsigned getNumInputs() const { return getInputs().size(); }

/// Returns the result type of the function as an actual return type or
/// explicit !cir.void
mlir::Type getReturnType() const;
/// Returns the result type of the function as an ArrayRef, enabling better
/// integration with generic MLIR utilities.
llvm::ArrayRef<mlir::Type> getReturnTypes() const;

/// Returns whether the function returns void.
/// Returns whether the function is returns void.
bool isVoid() const;

/// Returns a clone of this function type with the given argument
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ mlir::Type CIRGenTypes::ConvertFunctionTypeInternal(QualType QFT) {
assert(QFT.isCanonical());
const Type *Ty = QFT.getTypePtr();
const FunctionType *FT = cast<FunctionType>(QFT.getTypePtr());
// First, check whether we can build the full function type. If the function
// First, check whether we can build the full fucntion type. If the function
// type depends on an incomplete type (e.g. a struct or enum), we cannot lower
// the function type.
assert(isFuncTypeConvertible(FT) && "NYI");
Expand Down
39 changes: 10 additions & 29 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2225,26 +2225,6 @@ void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
getResAttrsAttrName(result.name));
}

// A specific version of function_interface_impl::parseFunctionSignature able to
// handle the "-> !void" special fake return type.
static ParseResult
parseFunctionSignature(OpAsmParser &parser, bool allowVariadic,
SmallVectorImpl<OpAsmParser::Argument> &arguments,
bool &isVariadic, SmallVectorImpl<Type> &resultTypes,
SmallVectorImpl<DictionaryAttr> &resultAttrs) {
if (function_interface_impl::parseFunctionArgumentList(parser, allowVariadic,
arguments, isVariadic))
return failure();
if (succeeded(parser.parseOptionalArrow())) {
if (parser.parseOptionalExclamationKeyword("!void").succeeded())
// This is just an empty return type and attribute.
return success();
return function_interface_impl::parseFunctionResultList(parser, resultTypes,
resultAttrs);
}
return success();
}

ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
llvm::SMLoc loc = parser.getCurrentLocation();

Expand Down Expand Up @@ -2305,8 +2285,9 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {

// Parse the function signature.
bool isVariadic = false;
if (parseFunctionSignature(parser, /*allowVariadic=*/true, arguments,
isVariadic, resultTypes, resultAttrs))
if (function_interface_impl::parseFunctionSignature(
parser, /*allowVariadic=*/true, arguments, isVariadic, resultTypes,
resultAttrs))
return failure();

for (auto &arg : arguments)
Expand Down Expand Up @@ -2509,8 +2490,13 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p.printSymbolName(getSymName());
auto fnType = getFunctionType();
llvm::SmallVector<Type, 1> resultTypes;
function_interface_impl::printFunctionSignature(
p, *this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
if (!fnType.isVoid())
function_interface_impl::printFunctionSignature(
p, *this, fnType.getInputs(), fnType.isVarArg(),
fnType.getReturnTypes());
else
function_interface_impl::printFunctionSignature(
p, *this, fnType.getInputs(), fnType.isVarArg(), {});

if (mlir::ArrayAttr annotations = getAnnotationsAttr()) {
p << ' ';
Expand Down Expand Up @@ -2579,11 +2565,6 @@ LogicalResult cir::FuncOp::verifyType() {
if (!getNoProto() && type.isVarArg() && type.getNumInputs() == 0)
return emitError()
<< "prototyped function must have at least one non-variadic input";
if (auto rt = type.getReturnTypes();
!rt.empty() && mlir::isa<cir::VoidType>(rt.front()))
return emitOpError("The return type for a function returning void should "
"be empty instead of an explicit !cir.void");

return success();
}

Expand Down
93 changes: 12 additions & 81 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <optional>

using cir::MissingFeatures;
Expand All @@ -43,16 +42,13 @@ using cir::MissingFeatures;
//===----------------------------------------------------------------------===//

static mlir::ParseResult
parseFuncType(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &returnTypes,
llvm::SmallVector<mlir::Type> &params, bool &isVarArg);

static void printFuncType(mlir::AsmPrinter &p,
mlir::ArrayRef<mlir::Type> returnTypes,
mlir::ArrayRef<mlir::Type> params, bool isVarArg);
parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
bool &isVarArg);
static void printFuncTypeArgs(mlir::AsmPrinter &p,
mlir::ArrayRef<mlir::Type> params, bool isVarArg);

static mlir::ParseResult parsePointerAddrSpace(mlir::AsmParser &p,
mlir::Attribute &addrSpaceAttr);

static void printPointerAddrSpace(mlir::AsmPrinter &p,
mlir::Attribute addrSpaceAttr);

Expand Down Expand Up @@ -917,46 +913,9 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const {
return get(llvm::to_vector(inputs), results[0], isVarArg());
}

// A special parser is needed for function returning void to consume the "!void"
// returned type in the case there is no alias defined.
static mlir::ParseResult
parseFuncTypeReturn(mlir::AsmParser &p,
llvm::SmallVector<mlir::Type> &returnTypes) {
if (p.parseOptionalExclamationKeyword("!void").succeeded())
// !void means no return type.
return p.parseLParen();
if (succeeded(p.parseOptionalLParen()))
// If we have already a '(', the function has no return type
return mlir::success();

mlir::Type type;
auto result = p.parseOptionalType(type);
if (!result.has_value())
return mlir::failure();
if (failed(*result) || isa<cir::VoidType>(type))
// No return type specified.
return p.parseLParen();
// Otherwise use the actual type.
returnTypes.push_back(type);
return p.parseLParen();
}

// A special pretty-printer for function returning void to emit a "!void"
// returned type. Note that there is no real type used here since it does not
// appear in the IR and thus the alias might not be defined and cannot be
// referred to. This is why this is a pure syntactic-sugar string which is used.
static void printFuncTypeReturn(mlir::AsmPrinter &p,
mlir::ArrayRef<mlir::Type> returnTypes) {
if (returnTypes.empty())
// Pretty-print no return type as "!void"
p << "!void ";
else
p << returnTypes << ' ';
}

static mlir::ParseResult
parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
bool &isVarArg) {
mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p,
llvm::SmallVector<mlir::Type> &params,
bool &isVarArg) {
isVarArg = false;
// `(` `)`
if (succeeded(p.parseOptionalRParen()))
Expand Down Expand Up @@ -986,10 +945,8 @@ parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
return p.parseRParen();
}

static void printFuncTypeArgs(mlir::AsmPrinter &p,
mlir::ArrayRef<mlir::Type> params,
bool isVarArg) {
p << '(';
void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef<mlir::Type> params,
bool isVarArg) {
llvm::interleaveComma(params, p,
[&p](mlir::Type type) { p.printType(type); });
if (isVarArg) {
Expand All @@ -1000,37 +957,11 @@ static void printFuncTypeArgs(mlir::AsmPrinter &p,
p << ')';
}

static mlir::ParseResult
parseFuncType(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &returnTypes,
llvm::SmallVector<mlir::Type> &params, bool &isVarArg) {
if (failed(parseFuncTypeReturn(p, returnTypes)))
return failure();
return parseFuncTypeArgs(p, params, isVarArg);
}

static void printFuncType(mlir::AsmPrinter &p,
mlir::ArrayRef<mlir::Type> returnTypes,
mlir::ArrayRef<mlir::Type> params, bool isVarArg) {
printFuncTypeReturn(p, returnTypes);
printFuncTypeArgs(p, params, isVarArg);
llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes() const {
return static_cast<detail::FuncTypeStorage *>(getImpl())->returnType;
}

// Return the actual return type or an explicit !cir.void if the function does
// not return anything
mlir::Type FuncType::getReturnType() const {
if (isVoid())
return cir::VoidType::get(getContext());
return static_cast<detail::FuncTypeStorage *>(getImpl())->returnTypes.front();
}

bool FuncType::isVoid() const {
auto rt = static_cast<detail::FuncTypeStorage *>(getImpl())->returnTypes;
assert(rt.empty() ||
!mlir::isa<cir::VoidType>(rt.front()) &&
"The return type for a function returning void should be empty "
"instead of a real !cir.void");
return rt.empty();
}
bool FuncType::isVoid() const { return mlir::isa<VoidType>(getReturnType()); }

//===----------------------------------------------------------------------===//
// MethodType Definitions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ FuncType LowerTypes::getFunctionType(const LowerFunctionInfo &FI) {
}
}

return FuncType::get(ArgTypes, resultType, FI.isVariadic());
return FuncType::get(getMLIRContext(), ArgTypes, resultType, FI.isVariadic());
}

/// Convert a CIR type to its ABI-specific default form.
Expand Down
35 changes: 0 additions & 35 deletions clang/test/CIR/IR/being_and_nothingness.cir

This file was deleted.

3 changes: 0 additions & 3 deletions mlir/include/mlir/IR/OpImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -922,9 +922,6 @@ class AsmParser {
/// Parse an optional keyword or string.
virtual ParseResult parseOptionalKeywordOrString(std::string *result) = 0;

/// Parse the given exclamation-prefixed keyword if present.
virtual ParseResult parseOptionalExclamationKeyword(StringRef keyword) = 0;

//===--------------------------------------------------------------------===//
// Attribute/Type Parsing
//===--------------------------------------------------------------------===//
Expand Down
22 changes: 0 additions & 22 deletions mlir/include/mlir/Interfaces/FunctionImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,6 @@ parseFunctionSignature(OpAsmParser &parser, bool allowVariadic,
bool &isVariadic, SmallVectorImpl<Type> &resultTypes,
SmallVectorImpl<DictionaryAttr> &resultAttrs);

/// Parse a function argument list using `parser`. The `allowVariadic` argument
/// indicates whether functions with variadic arguments are supported. The
/// trailing arguments are populated by this function with names, types,
/// attributes and locations of the arguments.
ParseResult
parseFunctionArgumentList(OpAsmParser &parser, bool allowVariadic,
SmallVectorImpl<OpAsmParser::Argument> &arguments,
bool &isVariadic);

/// Parse a function result list using `parser`.
///
/// function-result-list ::= function-result-list-parens
/// | non-function-type
/// function-result-list-parens ::= `(` `)`
/// | `(` function-result-list-no-parens `)`
/// function-result-list-no-parens ::= function-result (`,` function-result)*
/// function-result ::= type attribute-dict?
///
ParseResult
parseFunctionResultList(OpAsmParser &parser, SmallVectorImpl<Type> &resultTypes,
SmallVectorImpl<DictionaryAttr> &resultAttrs);

/// Parser implementation for function-like operations. Uses
/// `funcTypeBuilder` to construct the custom function type given lists of
/// input and output types. The parser sets the `typeAttrName` attribute to the
Expand Down
13 changes: 0 additions & 13 deletions mlir/lib/AsmParser/AsmParserImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,6 @@ class AsmParserImpl : public BaseT {
return parseOptionalString(result);
}

/// Parse the given exclamation-prefixed keyword if present.
ParseResult parseOptionalExclamationKeyword(StringRef keyword) override {
if (parser.getToken().isCodeCompletion())
return parser.codeCompleteOptionalTokens(keyword);

// Check that the current token has the same spelling.
if (!parser.getToken().is(Token::Kind::exclamation_identifier) ||
parser.getTokenSpelling() != keyword)
return failure();
parser.consumeToken();
return success();
}

//===--------------------------------------------------------------------===//
// Attribute Parsing
//===--------------------------------------------------------------------===//
Expand Down
Loading

0 comments on commit aa71766

Please sign in to comment.