Skip to content

Commit

Permalink
[CIR][ABI] Create target lowering library skeleton (llvm#643)
Browse files Browse the repository at this point in the history
This patch adds a new TargetLowering library that intends to add supoort
for lowering CIR code to target specific CIR code. It is largely based
on the original codegen library used to lower AST nodes to ABI/Target
-specific LLVM IR instructions. Because of this, each file has a comment
specifying the original codegen file that inspired the new file. The
idea is that anyone who wishes to expand this library can look at the
original codegen file to understand how to implement the new feature.

In some cases, CIRGen defers the handling of ABI/target-specific details
for a later stage in the pipeline. One reason for this is to keep the
intermediate representation on a higher-level, which makes it easier to
reason about and to perform optimizations. However, we still need to
lower such representation to a target-specific format at some point.
Some examples are ctor/dtors and calling conventions, which are not
fully handled by CIRGen. The new library will be responsible for these
lowerings.

Some files are empty but will eventually be used and a few getters and
methods where added to avoid unused warnings. Missing features in this
library are tracked in a dedicated MissingFeature.h header.
  • Loading branch information
sitio-couto authored and lanza committed Oct 12, 2024
1 parent 3f2b537 commit 02a4ebc
Show file tree
Hide file tree
Showing 36 changed files with 1,505 additions and 203 deletions.
226 changes: 226 additions & 0 deletions clang/include/clang/CIR/ABIArgInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
//==-- ABIArgInfo.h - Abstract info regarding ABI-specific arguments -------==//
//
// 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 ABIArgInfo and associated types used by CIR to track information
// regarding ABI-coerced types for function arguments and return values. This
// was moved to the common library as it might be used by both CIRGen and
// passes.
//
//===----------------------------------------------------------------------===//

#ifndef CIR_COMMON_ABIARGINFO_H
#define CIR_COMMON_ABIARGINFO_H

#include "mlir/IR/Types.h"
#include "clang/AST/Type.h"
#include <cstdint>

namespace cir {

/// Helper class to encapsulate information about how a specific C
/// type should be passed to or returned from a function.
class ABIArgInfo {
public:
enum Kind : uint8_t {
/// Pass the argument directly using the normal converted CIR type,
/// or by coercing to another specified type stored in 'CoerceToType'). If
/// an offset is specified (in UIntData), then the argument passed is offset
/// by some number of bytes in the memory representation. A dummy argument
/// is emitted before the real argument if the specified type stored in
/// "PaddingType" is not zero.
Direct,

/// Valid only for integer argument types. Same as 'direct' but
/// also emit a zer/sign extension attribute.
Extend,

/// Pass the argument indirectly via a hidden pointer with the
/// specified alignment (0 indicates default alignment) and address space.
Indirect,

/// Similar to Indirect, but the pointer may be to an
/// object that is otherwise referenced. The object is known to not be
/// modified through any other references for the duration of the call, and
/// the callee must not itself modify the object. Because C allows parameter
/// variables to be modified and guarantees that they have unique addresses,
/// the callee must defensively copy the object into a local variable if it
/// might be modified or its address might be compared. Since those are
/// uncommon, in principle this convention allows programs to avoid copies
/// in more situations. However, it may introduce *extra* copies if the
/// callee fails to prove that a copy is unnecessary and the caller
/// naturally produces an unaliased object for the argument.
IndirectAliased,

/// Ignore the argument (treat as void). Useful for void and empty
/// structs.
Ignore,

/// Only valid for aggregate argument types. The structure should
/// be expanded into consecutive arguments for its constituent fields.
/// Currently expand is only allowed on structures whose fields are all
/// scalar types or are themselves expandable types.
Expand,

/// Only valid for aggregate argument types. The structure
/// should be expanded into consecutive arguments corresponding to the
/// non-array elements of the type stored in CoerceToType.
/// Array elements in the type are assumed to be padding and skipped.
CoerceAndExpand,

// TODO: translate this idea to CIR! Define it for now just to ensure that
// we can assert it not being used
InAlloca,
KindFirst = Direct,
KindLast = InAlloca
};

private:
mlir::Type TypeData; // canHaveCoerceToType();
union {
mlir::Type PaddingType; // canHavePaddingType()
mlir::Type UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
};
struct DirectAttrInfo {
unsigned Offset;
unsigned Align;
};
struct IndirectAttrInfo {
unsigned Align;
unsigned AddrSpace;
};
union {
DirectAttrInfo DirectAttr; // isDirect() || isExtend()
IndirectAttrInfo IndirectAttr; // isIndirect()
unsigned AllocaFieldIndex; // isInAlloca()
};
Kind TheKind;
bool CanBeFlattened : 1; // isDirect()
bool SignExt : 1; // isExtend()

bool canHavePaddingType() const {
return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
isExpand();
}

void setPaddingType(mlir::Type T) {
assert(canHavePaddingType());
PaddingType = T;
}

public:
ABIArgInfo(Kind K = Direct)
: TypeData(nullptr), PaddingType(nullptr), DirectAttr{0, 0}, TheKind(K),
CanBeFlattened(false) {}

static ABIArgInfo getDirect(mlir::Type T = nullptr, unsigned Offset = 0,
mlir::Type Padding = nullptr,
bool CanBeFlattened = true, unsigned Align = 0) {
auto AI = ABIArgInfo(Direct);
AI.setCoerceToType(T);
AI.setPaddingType(Padding);
AI.setDirectOffset(Offset);
AI.setDirectAlign(Align);
AI.setCanBeFlattened(CanBeFlattened);
return AI;
}

static ABIArgInfo getSignExtend(clang::QualType Ty, mlir::Type T = nullptr) {
assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
auto AI = ABIArgInfo(Extend);
AI.setCoerceToType(T);
AI.setPaddingType(nullptr);
AI.setDirectOffset(0);
AI.setDirectAlign(0);
AI.setSignExt(true);
return AI;
}

static ABIArgInfo getZeroExtend(clang::QualType Ty, mlir::Type T = nullptr) {
assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
auto AI = ABIArgInfo(Extend);
AI.setCoerceToType(T);
AI.setPaddingType(nullptr);
AI.setDirectOffset(0);
AI.setDirectAlign(0);
AI.setSignExt(false);
return AI;
}

// ABIArgInfo will record the argument as being extended based on the sign of
// it's type.
static ABIArgInfo getExtend(clang::QualType Ty, mlir::Type T = nullptr) {
assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
if (Ty->hasSignedIntegerRepresentation())
return getSignExtend(Ty, T);
return getZeroExtend(Ty, T);
}

static ABIArgInfo getIgnore() { return ABIArgInfo(Ignore); }

Kind getKind() const { return TheKind; }
bool isDirect() const { return TheKind == Direct; }
bool isInAlloca() const { return TheKind == InAlloca; }
bool isExtend() const { return TheKind == Extend; }
bool isIndirect() const { return TheKind == Indirect; }
bool isIndirectAliased() const { return TheKind == IndirectAliased; }
bool isExpand() const { return TheKind == Expand; }
bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }

bool canHaveCoerceToType() const {
return isDirect() || isExtend() || isCoerceAndExpand();
}

// Direct/Extend accessors
unsigned getDirectOffset() const {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
return DirectAttr.Offset;
}

void setDirectOffset(unsigned Offset) {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
DirectAttr.Offset = Offset;
}

void setDirectAlign(unsigned Align) {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
DirectAttr.Align = Align;
}

void setSignExt(bool SExt) {
assert(isExtend() && "Invalid kind!");
SignExt = SExt;
}

void setCanBeFlattened(bool Flatten) {
assert(isDirect() && "Invalid kind!");
CanBeFlattened = Flatten;
}

bool getCanBeFlattened() const {
assert(isDirect() && "Invalid kind!");
return CanBeFlattened;
}

mlir::Type getPaddingType() const {
return (canHavePaddingType() ? PaddingType : nullptr);
}

mlir::Type getCoerceToType() const {
assert(canHaveCoerceToType() && "Invalid kind!");
return TypeData;
}

void setCoerceToType(mlir::Type T) {
assert(canHaveCoerceToType() && "Invalid kind!");
TypeData = T;
}
};

} // namespace cir

#endif // CIR_COMMON_ABIARGINFO_H
21 changes: 21 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,27 @@ struct MissingFeatures {
static bool supportisHomogeneousAggregateQueryForAArch64() { return false; }
static bool supportisEndianQueryForAArch64() { return false; }
static bool supportisAggregateTypeForABIAArch64() { return false; }

//===--- ABI lowering --===//

// Parameters may have additional attributes (e.g. [[noescape]]) that affect
// the compiler. This is not yet supported in CIR.
static bool extParamInfo() { return true; }

// LangOpts may affect lowering, but we do not carry this information into CIR
// just yet. Right now, it only instantiates the default lang options.
static bool langOpts() { return true; }

// Several type qualifiers are not yet supported in CIR, but important when
// evaluating ABI-specific lowering.
static bool qualifiedTypes() { return true; }

// We're ignoring several details regarding ABI-halding for Swift.
static bool swift() { return true; }

// Despite carrying some information about variadics, we are currently
// ignoring this to focus only on the code necessary to lower non-variadics.
static bool variadicFunctions() { return true; }
};

} // namespace cir
Expand Down
Loading

0 comments on commit 02a4ebc

Please sign in to comment.