Skip to content

[CIR] floating-point, pointer, and function types #120484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/CIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ include_directories(${MLIR_INCLUDE_DIR})
include_directories(${MLIR_TABLEGEN_OUTPUT_DIR})

add_subdirectory(Dialect)
add_subdirectory(Interfaces)
8 changes: 8 additions & 0 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
public:
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
: mlir::OpBuilder(&mlirContext) {}

cir::PointerType getPointerTo(mlir::Type ty) {
return cir::PointerType::get(getContext(), ty);
}

cir::PointerType getVoidPtrTy() {
return getPointerTo(cir::VoidType::get(getContext()));
}
};

} // namespace cir
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Types.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "clang/CIR/Interfaces/CIRFPTypeInterface.h"

namespace cir {

bool isAnyFloatingPointType(mlir::Type t);

} // namespace cir

//===----------------------------------------------------------------------===//
// CIR Dialect Tablegen'd Types
Expand Down
221 changes: 221 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define MLIR_CIR_DIALECT_CIR_TYPES

include "clang/CIR/Dialect/IR/CIRDialect.td"
include "clang/CIR/Interfaces/CIRFPTypeInterface.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
include "mlir/IR/AttrTypeBase.td"

Expand Down Expand Up @@ -129,4 +130,224 @@ def PrimitiveInt
: AnyTypeOf<[UInt8, UInt16, UInt32, UInt64, SInt8, SInt16, SInt32, SInt64],
"primitive int", "::cir::IntType">;

//===----------------------------------------------------------------------===//
// FloatType
//===----------------------------------------------------------------------===//

class CIR_FloatType<string name, string mnemonic>
: CIR_Type<name, mnemonic,
[
DeclareTypeInterfaceMethods<DataLayoutTypeInterface>,
DeclareTypeInterfaceMethods<CIRFPTypeInterface>,
]> {}

def CIR_Single : CIR_FloatType<"Single", "float"> {
let summary = "CIR single-precision 32-bit float type";
let description = [{
A 32-bit floating-point type whose format is IEEE-754 `binary32`. It
represents the types `float`, `_Float32`, and `std::float32_t` in C and C++.
}];
}

def CIR_Double : CIR_FloatType<"Double", "double"> {
let summary = "CIR double-precision 64-bit float type";
let description = [{
A 64-bit floating-point type whose format is IEEE-754 `binary64`. It
represents the types `double', '_Float64`, `std::float64_t`, and `_Float32x`
in C and C++. This is the underlying type for `long double` on some
platforms, including Windows.
}];
}

def CIR_FP16 : CIR_FloatType<"FP16", "f16"> {
let summary = "CIR half-precision 16-bit float type";
let description = [{
A 16-bit floating-point type whose format is IEEE-754 `binary16`. It
represents the types '_Float16` and `std::float16_t` in C and C++.
}];
}

def CIR_BFloat16 : CIR_FloatType<"BF16", "bf16"> {
let summary = "CIR bfloat16 16-bit float type";
let description = [{
A 16-bit floating-point type in the bfloat16 format, which is the same as
IEEE `binary32` except that the lower 16 bits of the mantissa are missing.
It represents the type `std::bfloat16_t` in C++, also spelled `__bf16` in
some implementations.
}];
}

def CIR_FP80 : CIR_FloatType<"FP80", "f80"> {
let summary = "CIR x87 80-bit float type";
let description = [{
An 80-bit floating-point type in the x87 extended precision format. The
size and alignment of the type are both 128 bits, even though only 80 of
those bits are used. This is the underlying type for `long double` on Linux
x86 platforms, and it is available as an extension in some implementations.
}];
}

def CIR_FP128 : CIR_FloatType<"FP128", "f128"> {
let summary = "CIR quad-precision 128-bit float type";
let description = [{
A 128-bit floating-point type whose format is IEEE-754 `binary128`. It
represents the types `_Float128` and `std::float128_t` in C and C++, and the
extension `__float128` in some implementations. This is the underlying type
for `long double` on some platforms including Linux Arm.
}];
}

def CIR_LongDouble : CIR_FloatType<"LongDouble", "long_double"> {
let summary = "CIR float type for `long double`";
let description = [{
A floating-point type that represents the `long double` type in C and C++.

The underlying floating-point format of a `long double` value depends on the
target platform and the implementation. The `underlying` parameter specifies
the CIR floating-point type that corresponds to this format. Underlying
types of IEEE 64-bit, IEEE 128-bit, x87 80-bit, and IBM's double-double
format are all in use.
}];

let parameters = (ins "mlir::Type":$underlying);

let assemblyFormat = [{
`<` $underlying `>`
}];

let genVerifyDecl = 1;
}

// Constraints

def CIR_AnyFloat: AnyTypeOf<[CIR_Single, CIR_Double, CIR_FP80, CIR_FP128, CIR_LongDouble,
CIR_FP16, CIR_BFloat16]>;
def CIR_AnyIntOrFloat: AnyTypeOf<[CIR_AnyFloat, CIR_IntType]>;

//===----------------------------------------------------------------------===//
// PointerType
//===----------------------------------------------------------------------===//

def CIR_PointerType : CIR_Type<"Pointer", "ptr",
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {

let summary = "CIR pointer type";
let description = [{
The `cir.ptr` type represents C and C++ pointer types and C++ reference
types, other than pointers-to-members. The `pointee` type is the type
pointed to.

TODO(CIR): The address space attribute is not yet implemented.
}];

let parameters = (ins "mlir::Type":$pointee);

let builders = [
TypeBuilderWithInferredContext<(ins "mlir::Type":$pointee), [{
return $_get(pointee.getContext(), pointee);
}]>,
TypeBuilder<(ins "mlir::Type":$pointee), [{
return $_get($_ctxt, pointee);
}]>
];

let assemblyFormat = [{
`<` $pointee `>`
}];

let genVerifyDecl = 1;

let skipDefaultBuilders = 1;

let extraClassDeclaration = [{
bool isVoidPtr() const {
return mlir::isa<cir::VoidType>(getPointee());
}
}];
}

//===----------------------------------------------------------------------===//
// FuncType
//===----------------------------------------------------------------------===//

def CIR_FuncType : CIR_Type<"Func", "func"> {
let summary = "CIR function type";
let description = [{
The `!cir.func` is a function type. It consists of a single return type, a
list of parameter types and can optionally be variadic.

Example:

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

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

let builders = [
TypeBuilderWithInferredContext<(ins
"llvm::ArrayRef<mlir::Type>":$inputs, "mlir::Type":$returnType,
CArg<"bool", "false">:$isVarArg), [{
return $_get(returnType.getContext(), inputs, returnType, isVarArg);
}]>
];

let extraClassDeclaration = [{
/// Returns whether the function is variadic.
bool isVarArg() const { return getVarArg(); }

/// Returns the `i`th input operand type. Asserts if out of bounds.
mlir::Type getInput(unsigned i) const { return getInputs()[i]; }

/// Returns the number of arguments to the function.
unsigned getNumInputs() const { return getInputs().size(); }

/// 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 is returns void.
bool isVoid() const;

/// Returns a clone of this function type with the given argument
/// and result types.
FuncType clone(mlir::TypeRange inputs, mlir::TypeRange results) const;
}];
}

//===----------------------------------------------------------------------===//
// Void type
//===----------------------------------------------------------------------===//

def CIR_VoidType : CIR_Type<"Void", "void"> {
let summary = "CIR void type";
let description = [{
The `!cir.void` type represents the C and C++ `void` type.
}];
let extraClassDeclaration = [{
std::string getAlias() const { return "void"; };
}];
}

// Constraints

// Pointer to void
def VoidPtr : Type<
And<[
CPred<"::mlir::isa<::cir::PointerType>($_self)">,
CPred<"::mlir::isa<::cir::VoidType>("
"::mlir::cast<::cir::PointerType>($_self).getPointee())">,
]>, "void*">,
BuildableType<
"cir::PointerType::get($_builder.getContext(),"
"cir::VoidType::get($_builder.getContext()))"> {
}

#endif // MLIR_CIR_DIALECT_CIR_TYPES
22 changes: 22 additions & 0 deletions clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===---------------------------------------------------------------------===//
//
// 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
//
//===---------------------------------------------------------------------===//
//
// Defines the interface to generically handle CIR floating-point types.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_H
#define LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_H

#include "mlir/IR/Types.h"
#include "llvm/ADT/APFloat.h"

/// Include the tablegen'd interface declarations.
#include "clang/CIR/Interfaces/CIRFPTypeInterface.h.inc"

#endif // LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_H
52 changes: 52 additions & 0 deletions clang/include/clang/CIR/Interfaces/CIRFPTypeInterface.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===- CIRFPTypeInterface.td - CIR FP Interface Definitions -----*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_TD
#define LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_TD

include "mlir/IR/OpBase.td"

def CIRFPTypeInterface : TypeInterface<"CIRFPTypeInterface"> {
let description = [{
Contains helper functions to query properties about a floating-point type.
}];
let cppNamespace = "::cir";

let methods = [
InterfaceMethod<[{
Returns the bit width of this floating-point type.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getWidth",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return llvm::APFloat::semanticsSizeInBits($_type.getFloatSemantics());
}]
>,
InterfaceMethod<[{
Return the mantissa width.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getFPMantissaWidth",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return llvm::APFloat::semanticsPrecision($_type.getFloatSemantics());
}]
>,
InterfaceMethod<[{
Return the float semantics of this floating-point type.
}],
/*retTy=*/"const llvm::fltSemantics &",
/*methodName=*/"getFloatSemantics"
>,
];
}

#endif // LLVM_CLANG_INCLUDE_CLANG_CIR_INTERFACES_CIRFPTYPEINTERFACE_TD
14 changes: 14 additions & 0 deletions clang/include/clang/CIR/Interfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# This replicates part of the add_mlir_interface cmake function from MLIR that
# cannot be used here. This happens because it expects to be run inside MLIR
# directory which is not the case for CIR (and also FIR, both have similar
# workarounds).

function(add_clang_mlir_type_interface interface)
set(LLVM_TARGET_DEFINITIONS ${interface}.td)
mlir_tablegen(${interface}.h.inc -gen-type-interface-decls)
mlir_tablegen(${interface}.cpp.inc -gen-type-interface-defs)
add_public_tablegen_target(MLIR${interface}IncGen)
add_dependencies(mlir-generic-headers MLIR${interface}IncGen)
endfunction()

add_clang_mlir_type_interface(CIRFPTypeInterface)
1 change: 1 addition & 0 deletions clang/lib/CIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)
add_subdirectory(Dialect)
add_subdirectory(CodeGen)
add_subdirectory(FrontendAction)
add_subdirectory(Interfaces)
12 changes: 12 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
public:
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
: CIRBaseBuilderTy(mlirContext), typeCache(tc) {}

cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const {
if (&format == &llvm::APFloat::IEEEdouble())
return cir::LongDoubleType::get(getContext(), typeCache.DoubleTy);
if (&format == &llvm::APFloat::x87DoubleExtended())
return cir::LongDoubleType::get(getContext(), typeCache.FP80Ty);
if (&format == &llvm::APFloat::IEEEquad())
return cir::LongDoubleType::get(getContext(), typeCache.FP128Ty);
if (&format == &llvm::APFloat::PPCDoubleDouble())
llvm_unreachable("NYI: PPC double-double format for long double");
llvm_unreachable("Unsupported format for long double");
}
};

} // namespace clang::CIRGen
Expand Down
Loading
Loading