Skip to content

Commit

Permalink
[CIR][ABI] Add X86_64 and AArch64 bool CC lowering (llvm#755)
Browse files Browse the repository at this point in the history
Implements calling convention lowering of bool arguments and return
value calling conventions for X86_64 and AArch64.

For x86_64, this is a bit of an odd case. In the orignal codegen bools
are represented as i8 everywhere, except for function arguments/return
values. In CIR, we don't allow i1 types, so bools are still represented
as `cir.bool` when in functions. However, when lowering to LLVM Dialect,
we need to ensure bools will be converted to i1 when in function's
argument/return values.
  • Loading branch information
sitio-couto authored and lanza committed Oct 2, 2024
1 parent 71e9ddf commit b083ca8
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 15 deletions.
3 changes: 2 additions & 1 deletion clang/include/clang/CIR/ABIArgInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ class ABIArgInfo {
}
static ABIArgInfo getExtend(mlir::Type Ty, mlir::Type T = nullptr) {
// NOTE(cir): The original can apply this method on both integers and
// enumerations, but in CIR, these two types are one and the same.
// enumerations, but in CIR, these two types are one and the same. Booleans
// will also fall into this category, but they have their own type.
if (mlir::isa<mlir::cir::IntType>(Ty) &&
mlir::cast<mlir::cir::IntType>(Ty).isSigned())
return getSignExtend(mlir::cast<mlir::cir::IntType>(Ty), T);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ clang::TypeInfo CIRLowerContext::getTypeInfoImpl(const Type T) const {
// TODO(cir): We should implement a better way to identify type kinds and use
// builting data layout interface for this.
auto typeKind = clang::Type::Builtin;
if (isa<IntType, SingleType, DoubleType>(T)) {
if (isa<IntType, SingleType, DoubleType, BoolType>(T)) {
typeKind = clang::Type::Builtin;
} else {
llvm_unreachable("Unhandled type class");
Expand All @@ -74,6 +74,11 @@ clang::TypeInfo CIRLowerContext::getTypeInfoImpl(const Type T) const {
Align = std::ceil((float)Width / 8) * 8;
break;
}
if (auto boolTy = dyn_cast<BoolType>(T)) {
Width = Target->getFloatWidth();
Align = Target->getFloatAlign();
break;
}
if (auto floatTy = dyn_cast<SingleType>(T)) {
Width = Target->getFloatWidth();
Align = Target->getFloatAlign();
Expand Down Expand Up @@ -153,6 +158,11 @@ bool CIRLowerContext::isPromotableIntegerType(Type T) const {
return cast<IntType>(T).getWidth() < 32;
}

// Bool are also handled here for codegen parity.
if (auto boolTy = dyn_cast<BoolType>(T)) {
return true;
}

// Enumerated types are promotable to their compatible integer types
// (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2).
// TODO(cir): CIR doesn't know if a integer originated from an enum. Improve
Expand Down
15 changes: 4 additions & 11 deletions clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "clang/CIR/ABIArgInfo.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "clang/CIR/TypeEvaluationKind.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -410,12 +411,9 @@ Value LowerFunction::rewriteCallOp(const LowerFunctionInfo &CallInfo,
switch (ArgInfo.getKind()) {
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
// NOTE(cir): While booleans are lowered directly as `i1`s in the
// original codegen, in CIR they require a trivial bitcast. This is
// handled here.

if (isa<BoolType>(info_it->type)) {
IRCallArgs[FirstIRArg] =
createBitcast(*I, ArgInfo.getCoerceToType(), *this);
IRCallArgs[FirstIRArg] = *I;
break;
}

Expand Down Expand Up @@ -514,11 +512,6 @@ Value LowerFunction::rewriteCallOp(const LowerFunctionInfo &CallInfo,

case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
// NOTE(cir): While booleans are lowered directly as `i1`s in the
// original codegen, in CIR they require a trivial bitcast. This is
// handled here.
assert(!isa<BoolType>(RetTy));

Type RetIRTy = RetTy;
if (RetAI.getCoerceToType() == RetIRTy && RetAI.getDirectOffset() == 0) {
switch (getEvaluationKind(RetTy)) {
Expand Down Expand Up @@ -564,7 +557,7 @@ ::cir::TypeEvaluationKind LowerFunction::getEvaluationKind(Type type) {
// FIXME(cir): Implement type classes for CIR types.
if (isa<StructType>(type))
return ::cir::TypeEvaluationKind::TEK_Aggregate;
if (isa<IntType, SingleType, DoubleType>(type))
if (isa<BoolType, IntType, SingleType, DoubleType>(type))
return ::cir::TypeEvaluationKind::TEK_Scalar;
llvm_unreachable("NYI");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ mlir::Type LowerTypes::convertType(Type T) {
/// keeping it here for parity's sake.

// Certain CIR types are already ABI-specific, so we just return them.
if (isa<IntType>(T)) {
if (isa<BoolType, IntType>(T)) {
return T;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "TargetInfo.h"
#include "clang/CIR/ABIArgInfo.h"
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
#include <memory>
Expand Down Expand Up @@ -157,6 +158,8 @@ void X86_64ABIInfo::classify(Type Ty, uint64_t OffsetBase, Class &Lo, Class &Hi,
Current = Class::SSE;
return;

} else if (isa<BoolType>(Ty)) {
Current = Class::Integer;
} else {
llvm::outs() << "Missing X86 classification for type " << Ty << "\n";
llvm_unreachable("NYI");
Expand Down Expand Up @@ -294,7 +297,7 @@ ::cir::ABIArgInfo X86_64ABIInfo::classifyReturnType(Type RetTy) const {
// enums directly as their unerlying integer types. NOTE(cir): For some
// reason, Clang does not set the coerce type here and delays it to
// arrangeLLVMFunctionInfo. We do the same to keep parity.
if (isa<IntType>(RetTy) && isPromotableIntegerTypeForABI(RetTy))
if (isa<IntType, BoolType>(RetTy) && isPromotableIntegerTypeForABI(RetTy))
return ABIArgInfo::getExtend(RetTy);
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ void Void(void) {

// Test call conv lowering for trivial usinged integer cases.

// CHECK: @_Z4Boolb(%arg0: !cir.bool loc({{.+}})) -> !cir.bool
bool Bool(bool a) {
// CHECK: cir.call @_Z4Boolb({{.+}}) : (!cir.bool) -> !cir.bool
return Bool(a);
}

// CHECK: cir.func @_Z5UCharh(%arg0: !u8i loc({{.+}})) -> !u8i
unsigned char UChar(unsigned char c) {
// CHECK: cir.call @_Z5UCharh(%2) : (!u8i) -> !u8i
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -fclangir-call-conv-lowering -emit-cir -mmlir --mlir-print-ir-after=cir-call-conv-lowering %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

// Test call conv lowering for trivial cases. //

// CHECK: @_Z4Voidv()
void Void(void) {
// CHECK: cir.call @_Z4Voidv() : () -> ()
Expand All @@ -9,6 +11,16 @@ void Void(void) {

// Test call conv lowering for trivial zeroext cases.

// Bools are a bit of an odd case in CIR's x86_64 representation: they are considered i8
// everywhere except in the function return/arguments, where they are considered i1. To
// match LLVM's behavior, we need to zero-extend them when passing them as arguments.

// CHECK: @_Z4Boolb(%arg0: !cir.bool {cir.zeroext} loc({{.+}})) -> (!cir.bool {cir.zeroext})
bool Bool(bool a) {
// CHECK: cir.call @_Z4Boolb({{.+}}) : (!cir.bool) -> !cir.bool
return Bool(a);
}

// CHECK: cir.func @_Z5UCharh(%arg0: !u8i {cir.zeroext} loc({{.+}})) -> (!u8i {cir.zeroext})
unsigned char UChar(unsigned char c) {
// CHECK: cir.call @_Z5UCharh(%2) : (!u8i) -> !u8i
Expand Down

0 comments on commit b083ca8

Please sign in to comment.