Skip to content

Commit

Permalink
Reapply and patch "[CIR][ABI] Apply CC lowering pass by default (llvm…
Browse files Browse the repository at this point in the history
…#842)" (llvm#944)

This reverts commit 8f699fd and fixes some issues, namely:
 
- CC lowering pass will no longer fail if the function has no AST
information that won't be used.
- Fixed CC lowering not disabling when running certain `cc1` compilation
commands.
- CC lowering can now be disabled when calling `cir-opt` and
`cir-translate`.
- Compilation commands that generate Object files should now invoke CC
lowering by default.
  • Loading branch information
sitio-couto authored and lanza committed Oct 19, 2024
1 parent d1b1222 commit 6d49e8b
Show file tree
Hide file tree
Showing 108 changed files with 498 additions and 385 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/CIR/Dialect/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ std::unique_ptr<Pass> createGotoSolverPass();
/// Create a pass to lower ABI-independent function definitions/calls.
std::unique_ptr<Pass> createCallConvLoweringPass();

void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm, bool useCCLowering);

//===----------------------------------------------------------------------===//
// Registration
Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/CIR/LowerToLLVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ class ModuleOp;
namespace cir {

namespace direct {
std::unique_ptr<llvm::Module>
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule,
llvm::LLVMContext &llvmCtx,
bool disableVerifier = false);
std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(
mlir::ModuleOp theModule, llvm::LLVMContext &llvmCtx,
bool disableVerifier = false, bool disableCCLowering = false);
}

// Lower directly from pristine CIR to LLVMIR.
Expand Down
41 changes: 41 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@
#ifndef CLANG_CIR_MISSINGFEATURES_H
#define CLANG_CIR_MISSINGFEATURES_H

constexpr bool cirMissingFeatureAssertionMode =
true; // Change to `false` to use llvm_unreachable

#define NOTE \
" Target lowering is now required. Disable it with " \
"-fno-clangir-call-conv-lowering."

// Special assertion to be used in the target lowering library.
#define cir_tl_assert(cond) assert((cond) && NOTE);

// Some assertions knowingly generate incorrect code. This macro allows us to
// switch between using `assert` and `llvm_unreachable` for these cases.
#define cir_assert_or_abort(cond, msg) \
do { \
if (cirMissingFeatureAssertionMode) { \
assert((cond) && msg NOTE); \
} else { \
llvm_unreachable(msg NOTE); \
} \
} while (0)

namespace cir {

struct MissingFeatures {
Expand Down Expand Up @@ -212,6 +233,26 @@ struct MissingFeatures {

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

static bool SPIRVABI() { return false; }

static bool AArch64TypeClassification() { return false; }

static bool X86ArgTypeClassification() { return false; }
static bool X86DefaultABITypeConvertion() { return false; }
static bool X86GetFPTypeAtOffset() { return false; }
static bool X86RetTypeClassification() { return false; }
static bool X86TypeClassification() { return false; }

static bool ABIClangTypeKind() { return false; }
static bool ABIEnterStructForCoercedAccess() { return false; }
static bool ABIFuncPtr() { return false; }
static bool ABIInRegAttribute() { return false; }
static bool ABINestedRecordLayout() { return false; }
static bool ABINoProtoFunctions() { return false; }
static bool ABIParameterCoercion() { return false; }
static bool ABIPointerParameterAttrs() { return false; }
static bool ABITransparentUnionHandling() { return false; }

//-- Missing AST queries

static bool CXXRecordDeclIsEmptyCXX11() { return false; }
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/CIR/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace direct {
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass();

/// Adds passes that fully lower CIR to the LLVMIR dialect.
void populateCIRToLLVMPasses(mlir::OpPassManager &pm);
void populateCIRToLLVMPasses(mlir::OpPassManager &pm, bool useCCLowering);

} // namespace direct
} // end namespace cir
Expand Down
11 changes: 7 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3037,10 +3037,6 @@ def fclangir_lib_opt : Flag<["-"], "fclangir-lib-opt">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
Alias<fclangir_lib_opt_EQ>,
HelpText<"Enable C/C++ library based optimizations">;
def fclangir_call_conv_lowering : Flag<["-"], "fclangir-call-conv-lowering">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable ClangIR calling convention lowering">,
MarshallingInfoFlag<FrontendOpts<"ClangIREnableCallConvLowering">>;
def fclangir_mem2reg : Flag<["-"], "fclangir-mem2reg">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable mem2reg on the flat ClangIR">,
Expand Down Expand Up @@ -3071,6 +3067,13 @@ defm clangir_analysis_only : BoolFOption<"clangir-analysis-only",
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Enable CIR analysis but keep traditional LLVM codegen (not through CIR)">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "">>;
// FIXME(cir): Remove this option once all pre-existing tests are compatible with
// the calling convention lowering pass.
defm clangir_call_conv_lowering : BoolFOption<"clangir-call-conv-lowering",
FrontendOpts<"ClangIRCallConvLowering">, DefaultTrue,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Transform CIR to abide to calling convetions during lowering">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Ignore calling convetion during lowering">,
BothFlags<[], [ClangOption, CC1Option], "">>;

def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ class FrontendOptions {
unsigned ClangIRLibOpt : 1;

// Enable Clang IR call conv lowering pass.
unsigned ClangIREnableCallConvLowering : 1;
unsigned ClangIRCallConvLowering : 1;

// Enable Clang IR mem2reg pass on the flat CIR.
unsigned ClangIREnableMem2Reg : 1;
Expand Down
11 changes: 4 additions & 7 deletions clang/lib/CIR/CodeGen/CIRPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,8 @@ mlir::LogicalResult runCIRToCIRPasses(

pm.addPass(mlir::createLoweringPreparePass(&astCtx));

// FIXME(cir): This pass should run by default, but it is lacking support for
// several code bits. Once it's more mature, we should fix this.
if (enableCallConvLowering)
pm.addPass(mlir::createCallConvLoweringPass());

if (flattenCIR || enableMem2Reg)
mlir::populateCIRPreLoweringPasses(pm);
mlir::populateCIRPreLoweringPasses(pm, enableCallConvLowering);

if (enableMem2Reg)
pm.addPass(mlir::createMem2Reg());
Expand All @@ -101,7 +96,9 @@ mlir::LogicalResult runCIRToCIRPasses(

namespace mlir {

void populateCIRPreLoweringPasses(OpPassManager &pm) {
void populateCIRPreLoweringPasses(OpPassManager &pm, bool useCCLowering) {
if (useCCLowering)
pm.addPass(createCallConvLoweringPass());
pm.addPass(createHoistAllocasPass());
pm.addPass(createFlattenCFGPass());
pm.addPass(createGotoSolverPass());
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//


#include "TargetLowering/LowerModule.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"

#define GEN_PASS_DEF_CALLCONVLOWERING
#include "clang/CIR/Dialect/Passes.h.inc"
Expand All @@ -36,9 +36,6 @@ struct CallConvLoweringPattern : public OpRewritePattern<FuncOp> {

const auto module = op->getParentOfType<mlir::ModuleOp>();

if (!op.getAst())
return op.emitError("function has no AST information");

auto modOp = op->getParentOfType<ModuleOp>();
std::unique_ptr<LowerModule> lowerModule =
createLowerModule(modOp, rewriter);
Expand All @@ -48,6 +45,12 @@ struct CallConvLoweringPattern : public OpRewritePattern<FuncOp> {
auto calls = op.getSymbolUses(module);
if (calls.has_value()) {
for (auto call : calls.value()) {
// FIXME(cir): Function pointers are ignored.
if (isa<GetGlobalOp>(call.getUser())) {
cir_assert_or_abort(!::cir::MissingFeatures::ABIFuncPtr(), "NYI");
continue;
}

auto callOp = cast<CallOp>(call.getUser());
if (lowerModule->rewriteFunctionCall(callOp, op).failed())
return failure();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ bool ABIInfo::isPromotableIntegerTypeForABI(Type Ty) const {
if (getContext().isPromotableIntegerType(Ty))
return true;

assert(!::cir::MissingFeatures::fixedWidthIntegers());
cir_tl_assert(!::cir::MissingFeatures::fixedWidthIntegers());

return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,22 @@ bool classifyReturnType(const CIRCXXABI &CXXABI, LowerFunctionInfo &FI,
Type Ty = FI.getReturnType();

if (const auto RT = dyn_cast<StructType>(Ty)) {
assert(!::cir::MissingFeatures::isCXXRecordDecl());
cir_tl_assert(!::cir::MissingFeatures::isCXXRecordDecl());
}

return CXXABI.classifyReturnType(FI);
}

bool isAggregateTypeForABI(Type T) {
assert(!::cir::MissingFeatures::functionMemberPointerType());
cir_tl_assert(!::cir::MissingFeatures::functionMemberPointerType());
return !LowerFunction::hasScalarEvaluationKind(T);
}

Type useFirstFieldIfTransparentUnion(Type Ty) {
if (auto RT = dyn_cast<StructType>(Ty)) {
if (RT.isUnion())
llvm_unreachable("NYI");
cir_assert_or_abort(
!::cir::MissingFeatures::ABITransparentUnionHandling(), "NYI");
}
return Ty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ clang::TypeInfo CIRLowerContext::getTypeInfoImpl(const Type T) const {
} else if (isa<StructType>(T)) {
typeKind = clang::Type::Record;
} else {
llvm_unreachable("Unhandled type class");
cir_assert_or_abort(!::cir::MissingFeatures::ABIClangTypeKind(),
"Unhandled type class");
// FIXME(cir): Completely wrong. Just here to make it non-blocking.
typeKind = clang::Type::Builtin;
}

// FIXME(cir): Here we fetch the width and alignment of a type considering the
Expand Down Expand Up @@ -96,10 +99,10 @@ clang::TypeInfo CIRLowerContext::getTypeInfoImpl(const Type T) const {
}
case clang::Type::Record: {
const auto RT = dyn_cast<StructType>(T);
assert(!::cir::MissingFeatures::tagTypeClassAbstraction());
cir_tl_assert(!::cir::MissingFeatures::tagTypeClassAbstraction());

// Only handle TagTypes (names types) for now.
assert(RT.getName() && "Anonymous record is NYI");
cir_tl_assert(RT.getName() && "Anonymous record is NYI");

// NOTE(cir): Clang does some hanlding of invalid tagged declarations here.
// Not sure if this is necessary in CIR.
Expand All @@ -111,22 +114,22 @@ clang::TypeInfo CIRLowerContext::getTypeInfoImpl(const Type T) const {
const CIRRecordLayout &Layout = getCIRRecordLayout(RT);
Width = toBits(Layout.getSize());
Align = toBits(Layout.getAlignment());
assert(!::cir::MissingFeatures::recordDeclHasAlignmentAttr());
cir_tl_assert(!::cir::MissingFeatures::recordDeclHasAlignmentAttr());
break;
}
default:
llvm_unreachable("Unhandled type class");
}

assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
cir_tl_assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
return clang::TypeInfo(Width, Align, AlignRequirement);
}

Type CIRLowerContext::initBuiltinType(clang::BuiltinType::Kind K) {
Type Ty;

// NOTE(cir): Clang does more stuff here. Not sure if we need to do the same.
assert(!::cir::MissingFeatures::qualifiedTypes());
cir_tl_assert(!::cir::MissingFeatures::qualifiedTypes());
switch (K) {
case clang::BuiltinType::Char_S:
Ty = IntType::get(getMLIRContext(), 8, true);
Expand All @@ -141,8 +144,8 @@ Type CIRLowerContext::initBuiltinType(clang::BuiltinType::Kind K) {

void CIRLowerContext::initBuiltinTypes(const clang::TargetInfo &Target,
const clang::TargetInfo *AuxTarget) {
assert((!this->Target || this->Target == &Target) &&
"Incorrect target reinitialization");
cir_tl_assert((!this->Target || this->Target == &Target) &&
"Incorrect target reinitialization");
this->Target = &Target;
this->AuxTarget = AuxTarget;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@ CIRRecordLayout::CIRRecordLayout(
FieldOffsets.insert(FieldOffsets.end(), fieldoffsets.begin(),
fieldoffsets.end());

assert(!PrimaryBase && "Layout for class with inheritance is NYI");
cir_tl_assert(!PrimaryBase && "Layout for class with inheritance is NYI");
// CXXInfo->PrimaryBase.setPointer(PrimaryBase);
assert(!IsPrimaryBaseVirtual && "Layout for virtual base class is NYI");
cir_tl_assert(!IsPrimaryBaseVirtual &&
"Layout for virtual base class is NYI");
// CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual);
CXXInfo->NonVirtualSize = nonvirtualsize;
CXXInfo->NonVirtualAlignment = nonvirtualalignment;
CXXInfo->PreferredNVAlignment = preferrednvalignment;
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
// FIXME(cir): Initialize base classes offsets.
assert(!::cir::MissingFeatures::getCXXRecordBases());
cir_tl_assert(!::cir::MissingFeatures::getCXXRecordBases());
CXXInfo->HasOwnVFPtr = hasOwnVFPtr;
CXXInfo->VBPtrOffset = vbptroffset;
CXXInfo->HasExtendableVFPtr = hasExtendableVFPtr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class CIRToCIRArgMapping {
unsigned totalIRArgs() const { return TotalIRArgs; }

bool hasPaddingArg(unsigned ArgNo) const {
assert(ArgNo < ArgInfo.size());
cir_tl_assert(ArgNo < ArgInfo.size());
return ArgInfo[ArgNo].PaddingArgIndex != InvalidIndex;
}

Expand All @@ -77,7 +77,7 @@ class CIRToCIRArgMapping {
onlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size();
for (LowerFunctionInfo::const_arg_iterator I = FI.arg_begin();
ArgNo < NumArgs; ++I, ++ArgNo) {
assert(I != FI.arg_end());
cir_tl_assert(I != FI.arg_end());
// Type ArgType = I->type;
const ::cir::ABIArgInfo &AI = I->info;
// Collect data about IR arguments corresponding to Clang argument ArgNo.
Expand All @@ -91,7 +91,7 @@ class CIRToCIRArgMapping {
case ::cir::ABIArgInfo::Extend:
case ::cir::ABIArgInfo::Direct: {
// FIXME(cir): handle sseregparm someday...
assert(AI.getCoerceToType() && "Missing coerced type!!");
cir_tl_assert(AI.getCoerceToType() && "Missing coerced type!!");
StructType STy = dyn_cast<StructType>(AI.getCoerceToType());
if (AI.isDirect() && AI.getCanBeFlattened() && STy) {
llvm_unreachable("NYI");
Expand All @@ -114,7 +114,7 @@ class CIRToCIRArgMapping {
if (IRArgNo == 1 && SwapThisWithSRet)
IRArgNo++;
}
assert(ArgNo == ArgInfo.size());
cir_tl_assert(ArgNo == ArgInfo.size());

if (::cir::MissingFeatures::inallocaArgs()) {
llvm_unreachable("NYI");
Expand All @@ -126,7 +126,7 @@ class CIRToCIRArgMapping {
/// Returns index of first IR argument corresponding to ArgNo, and their
/// quantity.
std::pair<unsigned, unsigned> getIRArgs(unsigned ArgNo) const {
assert(ArgNo < ArgInfo.size());
cir_tl_assert(ArgNo < ArgInfo.size());
return std::make_pair(ArgInfo[ArgNo].FirstArgIndex,
ArgInfo[ArgNo].NumberOfArgs);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class ItaniumCXXABI : public CIRCXXABI {

// FIXME(cir): This expects a CXXRecordDecl! Not any record type.
RecordArgABI getRecordArgABI(const StructType RD) const override {
assert(!::cir::MissingFeatures::recordDeclIsCXXDecl());
cir_tl_assert(!::cir::MissingFeatures::recordDeclIsCXXDecl());
// If C++ prohibits us from making a copy, pass by address.
assert(!::cir::MissingFeatures::recordDeclCanPassInRegisters());
cir_tl_assert(!::cir::MissingFeatures::recordDeclCanPassInRegisters());
return RAA_Default;
}
};
Expand Down Expand Up @@ -76,7 +76,7 @@ CIRCXXABI *CreateItaniumCXXABI(LowerModule &LM) {
case clang::TargetCXXABI::AppleARM64:
// TODO: this isn't quite right, clang uses AppleARM64CXXABI which inherits
// from ARMCXXABI. We'll have to follow suit.
assert(!::cir::MissingFeatures::appleArm64CXXABI());
cir_tl_assert(!::cir::MissingFeatures::appleArm64CXXABI());
return new ItaniumCXXABI(LM, /*UseARMMethodPtrABI=*/true,
/*UseARMGuardVarABI=*/true);

Expand Down
Loading

0 comments on commit 6d49e8b

Please sign in to comment.