[clang] [CIR] Cleanup support for C functions (PR #136854)
@@ -13,20 +13,76 @@ #include "CIRGenCall.h" #include "CIRGenFunction.h" +#include "CIRGenFunctionInfo.h" #include "clang/CIR/MissingFeatures.h" using namespace clang; using namespace clang::CIRGen; -CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) { - void *buffer = operator new(totalSizeToAlloc(1)); +CIRGenFunctionInfo * +CIRGenFunctionInfo::create(CanQualType resultType, + llvm::ArrayRef argTypes, + RequiredArgs required) { + void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1)); CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo(); + + fi->required = required; + fi->numArgs = argTypes.size(); fi->getArgsBuffer()[0].type = resultType; + for (unsigned i = 0; i < argTypes.size(); ++i) +fi->getArgsBuffer()[i + 1].type = argTypes[i]; return fi; } +cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) { + bool inserted = functionsBeingProcessed.insert(&fi).second; + assert(inserted && "Recursively being processed?"); + + mlir::Type resultType = nullptr; + const cir::ABIArgInfo &retAI = fi.getReturnInfo(); + + switch (retAI.getKind()) { + case cir::ABIArgInfo::Ignore: +// TODO(CIR): This should probably be the None type from the builtin +// dialect. +resultType = nullptr; +break; + + case cir::ABIArgInfo::Direct: +resultType = retAI.getCoerceToType(); +break; + + default: +assert(false && "NYI"); + } + + SmallVector argTypes; + unsigned argNo = 0; + CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(), + ie = it + fi.getNumRequiredArgs(); + for (; it != ie; ++it, ++argNo) { +const auto &argInfo = it->info; + +switch (argInfo.getKind()) { +default: + llvm_unreachable("NYI"); +case cir::ABIArgInfo::Direct: + mlir::Type argType = argInfo.getCoerceToType(); + argTypes.push_back(argType); + break; +} + } + + bool erased = functionsBeingProcessed.erase(&fi); + assert(erased && "Not in set?"); el-ev wrote: Thank you! I wasn't aware of the purpose of that line before, and I understand its purpose now. https://github.com/llvm/llvm-project/pull/136854 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Cleanup support for C functions (PR #136854)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/136854 >From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Wed, 23 Apr 2025 20:23:09 +0800 Subject: [PATCH 1/2] [CIR] Cleanup support for C functions --- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 82 +++- clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 37 - clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++- clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 ++- clang/test/CIR/CodeGen/basic.c | 13 7 files changed, 232 insertions(+), 29 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 69266f79a88a5..b223bc494f928 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -13,20 +13,76 @@ #include "CIRGenCall.h" #include "CIRGenFunction.h" +#include "CIRGenFunctionInfo.h" #include "clang/CIR/MissingFeatures.h" using namespace clang; using namespace clang::CIRGen; -CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) { - void *buffer = operator new(totalSizeToAlloc(1)); +CIRGenFunctionInfo * +CIRGenFunctionInfo::create(CanQualType resultType, + llvm::ArrayRef argTypes, + RequiredArgs required) { + void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1)); CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo(); + + fi->required = required; + fi->numArgs = argTypes.size(); fi->getArgsBuffer()[0].type = resultType; + for (unsigned i = 0; i < argTypes.size(); ++i) +fi->getArgsBuffer()[i + 1].type = argTypes[i]; return fi; } +cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) { + bool inserted = functionsBeingProcessed.insert(&fi).second; + assert(inserted && "Recursively being processed?"); + + mlir::Type resultType = nullptr; + const cir::ABIArgInfo &retAI = fi.getReturnInfo(); + + switch (retAI.getKind()) { + case cir::ABIArgInfo::Ignore: +// TODO(CIR): This should probably be the None type from the builtin +// dialect. +resultType = nullptr; +break; + + case cir::ABIArgInfo::Direct: +resultType = retAI.getCoerceToType(); +break; + + default: +assert(false && "NYI"); + } + + SmallVector argTypes; + unsigned argNo = 0; + CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(), + ie = it + fi.getNumRequiredArgs(); + for (; it != ie; ++it, ++argNo) { +const auto &argInfo = it->info; + +switch (argInfo.getKind()) { +default: + llvm_unreachable("NYI"); +case cir::ABIArgInfo::Direct: + mlir::Type argType = argInfo.getCoerceToType(); + argTypes.push_back(argType); + break; +} + } + + bool erased = functionsBeingProcessed.erase(&fi); + assert(erased && "Not in set?"); + + return cir::FuncType::get(argTypes, +(resultType ? resultType : builder.getVoidTy()), +fi.isVariadic()); +} + CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { assert(!cir::MissingFeatures::opCallVirtual()); return *this; @@ -35,6 +91,9 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const FunctionType *fnType) { + + RequiredArgs required = RequiredArgs::All; + if (const auto *proto = dyn_cast(fnType)) { if (proto->isVariadic()) cgm.errorNYI("call to variadic function"); @@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, CanQualType retType = fnType->getReturnType() ->getCanonicalTypeUnqualified() .getUnqualifiedType(); - return cgt.arrangeCIRFunctionInfo(retType); + return cgt.arrangeCIRFunctionInfo(retType, {}, required); } const CIRGenFunctionInfo & @@ -71,6 +130,23 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, return builder.createCallOp(callLoc, directFuncOp); } +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) { + SmallVector argTypes; + for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) +argTypes.push_back(fpt->getParamType(i)); + RequiredArgs required = RequiredArgs::forPrototypePlus(fpt); + + CanQualType resultType = fpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, argTypes, required); +} + +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) { + CanQualType resultType = fnpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
[clang] [CIR] Cleanup support for C functions (PR #136854)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/136854 >From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Wed, 23 Apr 2025 20:23:09 +0800 Subject: [PATCH 1/2] [CIR] Cleanup support for C functions --- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 82 +++- clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 37 - clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++- clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 ++- clang/test/CIR/CodeGen/basic.c | 13 7 files changed, 232 insertions(+), 29 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 69266f79a88a5..b223bc494f928 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -13,20 +13,76 @@ #include "CIRGenCall.h" #include "CIRGenFunction.h" +#include "CIRGenFunctionInfo.h" #include "clang/CIR/MissingFeatures.h" using namespace clang; using namespace clang::CIRGen; -CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) { - void *buffer = operator new(totalSizeToAlloc(1)); +CIRGenFunctionInfo * +CIRGenFunctionInfo::create(CanQualType resultType, + llvm::ArrayRef argTypes, + RequiredArgs required) { + void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1)); CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo(); + + fi->required = required; + fi->numArgs = argTypes.size(); fi->getArgsBuffer()[0].type = resultType; + for (unsigned i = 0; i < argTypes.size(); ++i) +fi->getArgsBuffer()[i + 1].type = argTypes[i]; return fi; } +cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) { + bool inserted = functionsBeingProcessed.insert(&fi).second; + assert(inserted && "Recursively being processed?"); + + mlir::Type resultType = nullptr; + const cir::ABIArgInfo &retAI = fi.getReturnInfo(); + + switch (retAI.getKind()) { + case cir::ABIArgInfo::Ignore: +// TODO(CIR): This should probably be the None type from the builtin +// dialect. +resultType = nullptr; +break; + + case cir::ABIArgInfo::Direct: +resultType = retAI.getCoerceToType(); +break; + + default: +assert(false && "NYI"); + } + + SmallVector argTypes; + unsigned argNo = 0; + CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(), + ie = it + fi.getNumRequiredArgs(); + for (; it != ie; ++it, ++argNo) { +const auto &argInfo = it->info; + +switch (argInfo.getKind()) { +default: + llvm_unreachable("NYI"); +case cir::ABIArgInfo::Direct: + mlir::Type argType = argInfo.getCoerceToType(); + argTypes.push_back(argType); + break; +} + } + + bool erased = functionsBeingProcessed.erase(&fi); + assert(erased && "Not in set?"); + + return cir::FuncType::get(argTypes, +(resultType ? resultType : builder.getVoidTy()), +fi.isVariadic()); +} + CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { assert(!cir::MissingFeatures::opCallVirtual()); return *this; @@ -35,6 +91,9 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const FunctionType *fnType) { + + RequiredArgs required = RequiredArgs::All; + if (const auto *proto = dyn_cast(fnType)) { if (proto->isVariadic()) cgm.errorNYI("call to variadic function"); @@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, CanQualType retType = fnType->getReturnType() ->getCanonicalTypeUnqualified() .getUnqualifiedType(); - return cgt.arrangeCIRFunctionInfo(retType); + return cgt.arrangeCIRFunctionInfo(retType, {}, required); } const CIRGenFunctionInfo & @@ -71,6 +130,23 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, return builder.createCallOp(callLoc, directFuncOp); } +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) { + SmallVector argTypes; + for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) +argTypes.push_back(fpt->getParamType(i)); + RequiredArgs required = RequiredArgs::forPrototypePlus(fpt); + + CanQualType resultType = fpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, argTypes, required); +} + +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) { + CanQualType resultType = fnpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
[clang] [CIR] Cleanup support for C functions (PR #136854)
@@ -233,6 +233,19 @@ int f8(int *p) { // OGCG: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8 // OGCG: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4 + +void f9() {} el-ev wrote: I'm actually unsure what kind of new tests would be appropriate. Do you have any suggestions on what I should add? https://github.com/llvm/llvm-project/pull/136854 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream initial support for union type (PR #137501)
https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/137501 Closes #136059 >From f27d8d2f2ecbf65479601f1d21206b1cb4d9ef6a Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Sun, 27 Apr 2025 15:16:19 +0800 Subject: [PATCH] [CIR] Upstream initial support for union type --- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 1 + clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 25 ++-- clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 2 +- .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 93 +++- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 39 +++-- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 +- clang/test/CIR/CodeGen/union.c| 135 +- 7 files changed, 275 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 0a821e152d353..afb7da1fa011d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -494,6 +494,7 @@ def CIR_RecordType : CIR_Type<"Record", "record", bool isComplete() const { return !isIncomplete(); }; bool isIncomplete() const; +mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const; size_t getNumElements() const { return getMembers().size(); }; std::string getKindAsStr() { switch (getKind()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 0a518c0fd935d..f3bcffe042280 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -317,20 +317,25 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { } unsigned recordCVR = base.getVRQualifiers(); - if (rec->isUnion()) { -cgm.errorNYI(field->getSourceRange(), "emitLValueForField: union"); -return LValue(); - } - assert(!cir::MissingFeatures::preservedAccessIndexRegion()); llvm::StringRef fieldName = field->getName(); - const CIRGenRecordLayout &layout = - cgm.getTypes().getCIRGenRecordLayout(field->getParent()); - unsigned fieldIndex = layout.getCIRFieldNo(field); - assert(!cir::MissingFeatures::lambdaFieldToName()); + if (rec->isUnion()) { + unsigned fieldIndex = field->getFieldIndex(); + assert(!cir::MissingFeatures::lambdaFieldToName()); +addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); - addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); + } else { +assert(!cir::MissingFeatures::preservedAccessIndexRegion()); + +const CIRGenRecordLayout &layout = +cgm.getTypes().getCIRGenRecordLayout(field->getParent()); +unsigned fieldIndex = layout.getCIRFieldNo(field); + +assert(!cir::MissingFeatures::lambdaFieldToName()); + +addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); + } // If this is a reference field, load the reference right now. if (fieldType->isReferenceType()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 368a6cb27c0fd..e006a77c6e7d6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -1,4 +1,4 @@ -//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp index 83aba256cd48e..778a178505684 100644 --- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp @@ -56,7 +56,7 @@ struct CIRRecordLowering final { }; // The constructor. CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl, -bool isPacked); +bool packed); /// Constructs a MemberInfo instance from an offset and mlir::Type. MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) { @@ -64,6 +64,7 @@ struct CIRRecordLowering final { } void lower(); + void lowerUnion(); /// Determines if we need a packed llvm struct. void determinePacked(); @@ -83,6 +84,10 @@ struct CIRRecordLowering final { return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty)); } + bool isZeroInitializable(const FieldDecl *fd) { +return cirGenTypes.isZeroInitializable(fd->getType()); + } + /// Wraps cir::IntType with some implicit arguments. mlir::Type getUIntNType(uint64_t numBits) { unsigned alignedBits = llvm::PowerOf2Ceil(numBits); @@ -121,6 +126,13 @@ struct CIRRecordLowering final { /// Fills out the structures that are ultimately consumed. void fillOutputFields(); + void appen
[clang] [CIR] Upstream initial support for union type (PR #137501)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/137501 >From b8011997fdc2548be80dd9305d758466a66cee4c Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Sun, 27 Apr 2025 15:16:19 +0800 Subject: [PATCH] [CIR] Upstream initial support for union type --- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 1 + clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 25 ++-- clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 2 +- .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 94 +++- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 40 -- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 +- clang/test/CIR/CodeGen/union.c| 135 +- 7 files changed, 276 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 0a821e152d353..afb7da1fa011d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -494,6 +494,7 @@ def CIR_RecordType : CIR_Type<"Record", "record", bool isComplete() const { return !isIncomplete(); }; bool isIncomplete() const; +mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const; size_t getNumElements() const { return getMembers().size(); }; std::string getKindAsStr() { switch (getKind()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 0a518c0fd935d..9069d1a2cf6ac 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -317,20 +317,25 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { } unsigned recordCVR = base.getVRQualifiers(); - if (rec->isUnion()) { -cgm.errorNYI(field->getSourceRange(), "emitLValueForField: union"); -return LValue(); - } - assert(!cir::MissingFeatures::preservedAccessIndexRegion()); llvm::StringRef fieldName = field->getName(); - const CIRGenRecordLayout &layout = - cgm.getTypes().getCIRGenRecordLayout(field->getParent()); - unsigned fieldIndex = layout.getCIRFieldNo(field); - assert(!cir::MissingFeatures::lambdaFieldToName()); + if (rec->isUnion()) { +unsigned fieldIndex = field->getFieldIndex(); +assert(!cir::MissingFeatures::lambdaFieldToName()); +addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); + + } else { +assert(!cir::MissingFeatures::preservedAccessIndexRegion()); + +const CIRGenRecordLayout &layout = +cgm.getTypes().getCIRGenRecordLayout(field->getParent()); +unsigned fieldIndex = layout.getCIRFieldNo(field); - addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); +assert(!cir::MissingFeatures::lambdaFieldToName()); + +addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); + } // If this is a reference field, load the reference right now. if (fieldType->isReferenceType()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 368a6cb27c0fd..e006a77c6e7d6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -1,4 +1,4 @@ -//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp index 83aba256cd48e..7b9631daacfdd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp @@ -56,7 +56,7 @@ struct CIRRecordLowering final { }; // The constructor. CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl, -bool isPacked); +bool packed); /// Constructs a MemberInfo instance from an offset and mlir::Type. MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) { @@ -64,6 +64,7 @@ struct CIRRecordLowering final { } void lower(); + void lowerUnion(); /// Determines if we need a packed llvm struct. void determinePacked(); @@ -83,6 +84,10 @@ struct CIRRecordLowering final { return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty)); } + bool isZeroInitializable(const FieldDecl *fd) { +return cirGenTypes.isZeroInitializable(fd->getType()); + } + /// Wraps cir::IntType with some implicit arguments. mlir::Type getUIntNType(uint64_t numBits) { unsigned alignedBits = llvm::PowerOf2Ceil(numBits); @@ -121,6 +126,13 @@ struct CIRRecordLowering final { /// Fills out the structures that are ultimately consumed. void fillOutputFields(); + void appendPaddingBytes(CharUnits
[clang] [CIR] Upstream initial support for union type (PR #137501)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/137501 >From b8011997fdc2548be80dd9305d758466a66cee4c Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Sun, 27 Apr 2025 15:16:19 +0800 Subject: [PATCH 1/2] [CIR] Upstream initial support for union type --- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 1 + clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 25 ++-- clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 2 +- .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp | 94 +++- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 40 -- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 +- clang/test/CIR/CodeGen/union.c| 135 +- 7 files changed, 276 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 0a821e152d353..afb7da1fa011d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -494,6 +494,7 @@ def CIR_RecordType : CIR_Type<"Record", "record", bool isComplete() const { return !isIncomplete(); }; bool isIncomplete() const; +mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const; size_t getNumElements() const { return getMembers().size(); }; std::string getKindAsStr() { switch (getKind()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 0a518c0fd935d..9069d1a2cf6ac 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -317,20 +317,25 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { } unsigned recordCVR = base.getVRQualifiers(); - if (rec->isUnion()) { -cgm.errorNYI(field->getSourceRange(), "emitLValueForField: union"); -return LValue(); - } - assert(!cir::MissingFeatures::preservedAccessIndexRegion()); llvm::StringRef fieldName = field->getName(); - const CIRGenRecordLayout &layout = - cgm.getTypes().getCIRGenRecordLayout(field->getParent()); - unsigned fieldIndex = layout.getCIRFieldNo(field); - assert(!cir::MissingFeatures::lambdaFieldToName()); + if (rec->isUnion()) { +unsigned fieldIndex = field->getFieldIndex(); +assert(!cir::MissingFeatures::lambdaFieldToName()); +addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); + + } else { +assert(!cir::MissingFeatures::preservedAccessIndexRegion()); + +const CIRGenRecordLayout &layout = +cgm.getTypes().getCIRGenRecordLayout(field->getParent()); +unsigned fieldIndex = layout.getCIRFieldNo(field); - addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); +assert(!cir::MissingFeatures::lambdaFieldToName()); + +addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex); + } // If this is a reference field, load the reference right now. if (fieldType->isReferenceType()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 368a6cb27c0fd..e006a77c6e7d6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -1,4 +1,4 @@ -//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp index 83aba256cd48e..7b9631daacfdd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp @@ -56,7 +56,7 @@ struct CIRRecordLowering final { }; // The constructor. CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl, -bool isPacked); +bool packed); /// Constructs a MemberInfo instance from an offset and mlir::Type. MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) { @@ -64,6 +64,7 @@ struct CIRRecordLowering final { } void lower(); + void lowerUnion(); /// Determines if we need a packed llvm struct. void determinePacked(); @@ -83,6 +84,10 @@ struct CIRRecordLowering final { return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty)); } + bool isZeroInitializable(const FieldDecl *fd) { +return cirGenTypes.isZeroInitializable(fd->getType()); + } + /// Wraps cir::IntType with some implicit arguments. mlir::Type getUIntNType(uint64_t numBits) { unsigned alignedBits = llvm::PowerOf2Ceil(numBits); @@ -121,6 +126,13 @@ struct CIRRecordLowering final { /// Fills out the structures that are ultimately consumed. void fillOutputFields(); + void appendPaddingBytes(CharU
[clang] [CIR] Upstream initial support for union type (PR #137501)
@@ -5,25 +5,146 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s +union U1 { el-ev wrote: Padded and packed unions are added, `CIRGenTypes::isZeroInitializable` doesn't contain a path that returns false without triggering errorNYI. https://github.com/llvm/llvm-project/pull/137501 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream initial support for union type (PR #137501)
@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) { // TODO: implement verification return rl; } + +void CIRRecordLowering::lowerUnion() { + CharUnits layoutSize = astRecordLayout.getSize(); + mlir::Type storageType = nullptr; + bool seenNamedMember = false; + + // Iterate through the fields setting bitFieldInfo and the Fields array. Also + // locate the "most appropriate" storage type. The heuristic for finding the el-ev wrote: Removed https://github.com/llvm/llvm-project/pull/137501 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream initial support for union type (PR #137501)
@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) { // TODO: implement verification return rl; } + +void CIRRecordLowering::lowerUnion() { + CharUnits layoutSize = astRecordLayout.getSize(); + mlir::Type storageType = nullptr; + bool seenNamedMember = false; + + // Iterate through the fields setting bitFieldInfo and the Fields array. Also + // locate the "most appropriate" storage type. The heuristic for finding the + // storage type isn't necessary, the first (non-0-length-bitfield) field's + // type would work fine and be simpler but would be different than what we've + // been doing and cause lit tests to change. + for (const FieldDecl *field : recordDecl->fields()) { +mlir::Type fieldType; +if (field->isBitField()) + cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(), + "bitfields in lowerUnion"); +else + fieldType = getStorageType(field); + +fields[field->getCanonicalDecl()] = 0; el-ev wrote: Renamed them to `fieldIdxMap` https://github.com/llvm/llvm-project/pull/137501 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream initial support for union type (PR #137501)
@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) { // TODO: implement verification return rl; } + +void CIRRecordLowering::lowerUnion() { + CharUnits layoutSize = astRecordLayout.getSize(); + mlir::Type storageType = nullptr; + bool seenNamedMember = false; + + // Iterate through the fields setting bitFieldInfo and the Fields array. Also + // locate the "most appropriate" storage type. The heuristic for finding the + // storage type isn't necessary, the first (non-0-length-bitfield) field's + // type would work fine and be simpler but would be different than what we've + // been doing and cause lit tests to change. + for (const FieldDecl *field : recordDecl->fields()) { +mlir::Type fieldType; +if (field->isBitField()) + cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(), + "bitfields in lowerUnion"); +else + fieldType = getStorageType(field); + +fields[field->getCanonicalDecl()] = 0; + +// Compute zero-initializable status. +// This union might not be zero initialized: it may contain a pointer to +// data member which might have some exotic initialization sequence. +// If this is the case, then we aught not to try and come up with a "better" +// type, it might not be very easy to come up with a Constant which +// correctly initializes it. +if (!seenNamedMember) { + seenNamedMember = field->getIdentifier(); + if (!seenNamedMember) +if (const RecordDecl *fieldRD = field->getType()->getAsRecordDecl()) + seenNamedMember = fieldRD->findFirstNamedDataMember(); + if (seenNamedMember && !isZeroInitializable(field)) { +zeroInitializable = zeroInitializableAsBase = false; +storageType = fieldType; + } +} + +// Because our union isn't zero initializable, we won't be getting a better +// storage type. +if (!zeroInitializable) + continue; + +// Conditionally update our storage type if we've got a new "better" one. +if (!storageType || getAlignment(fieldType) > getAlignment(storageType) || +(getAlignment(fieldType) == getAlignment(storageType) && + getSize(fieldType) > getSize(storageType))) + storageType = fieldType; + +// NOTE(cir): Track all union member's types, not just the largest one. It +// allows for proper type-checking and retain more info for analisys. +fieldTypes.push_back(fieldType); + } + + if (!storageType) +cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(), + "No-storage Union NYI"); + + if (layoutSize < getSize(storageType)) +storageType = getByteArrayType(layoutSize); + + // NOTE(cir): Defer padding calculations to the lowering process. el-ev wrote: It was indeed confusing and not true, removed. https://github.com/llvm/llvm-project/pull/137501 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream initial support for union type (PR #137501)
@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) { // TODO: implement verification return rl; } + +void CIRRecordLowering::lowerUnion() { + CharUnits layoutSize = astRecordLayout.getSize(); + mlir::Type storageType = nullptr; + bool seenNamedMember = false; + + // Iterate through the fields setting bitFieldInfo and the Fields array. Also + // locate the "most appropriate" storage type. The heuristic for finding the + // storage type isn't necessary, the first (non-0-length-bitfield) field's + // type would work fine and be simpler but would be different than what we've + // been doing and cause lit tests to change. + for (const FieldDecl *field : recordDecl->fields()) { +mlir::Type fieldType; +if (field->isBitField()) + cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(), + "bitfields in lowerUnion"); +else + fieldType = getStorageType(field); + +fields[field->getCanonicalDecl()] = 0; + +// Compute zero-initializable status. +// This union might not be zero initialized: it may contain a pointer to +// data member which might have some exotic initialization sequence. +// If this is the case, then we aught not to try and come up with a "better" +// type, it might not be very easy to come up with a Constant which +// correctly initializes it. +if (!seenNamedMember) { el-ev wrote: If the first named member is a `RecordDecl`, it will trigger `ClangIR code gen Not Yet Implemented: isZeroInitializable for RecordType: 'S'` https://github.com/llvm/llvm-project/pull/137501 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Cleanup support for C functions (PR #136854)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/136854 >From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Wed, 23 Apr 2025 20:23:09 +0800 Subject: [PATCH 1/2] [CIR] Cleanup support for C functions --- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 82 +++- clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 37 - clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++- clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 ++- clang/test/CIR/CodeGen/basic.c | 13 7 files changed, 232 insertions(+), 29 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 69266f79a88a5..b223bc494f928 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -13,20 +13,76 @@ #include "CIRGenCall.h" #include "CIRGenFunction.h" +#include "CIRGenFunctionInfo.h" #include "clang/CIR/MissingFeatures.h" using namespace clang; using namespace clang::CIRGen; -CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) { - void *buffer = operator new(totalSizeToAlloc(1)); +CIRGenFunctionInfo * +CIRGenFunctionInfo::create(CanQualType resultType, + llvm::ArrayRef argTypes, + RequiredArgs required) { + void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1)); CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo(); + + fi->required = required; + fi->numArgs = argTypes.size(); fi->getArgsBuffer()[0].type = resultType; + for (unsigned i = 0; i < argTypes.size(); ++i) +fi->getArgsBuffer()[i + 1].type = argTypes[i]; return fi; } +cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) { + bool inserted = functionsBeingProcessed.insert(&fi).second; + assert(inserted && "Recursively being processed?"); + + mlir::Type resultType = nullptr; + const cir::ABIArgInfo &retAI = fi.getReturnInfo(); + + switch (retAI.getKind()) { + case cir::ABIArgInfo::Ignore: +// TODO(CIR): This should probably be the None type from the builtin +// dialect. +resultType = nullptr; +break; + + case cir::ABIArgInfo::Direct: +resultType = retAI.getCoerceToType(); +break; + + default: +assert(false && "NYI"); + } + + SmallVector argTypes; + unsigned argNo = 0; + CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(), + ie = it + fi.getNumRequiredArgs(); + for (; it != ie; ++it, ++argNo) { +const auto &argInfo = it->info; + +switch (argInfo.getKind()) { +default: + llvm_unreachable("NYI"); +case cir::ABIArgInfo::Direct: + mlir::Type argType = argInfo.getCoerceToType(); + argTypes.push_back(argType); + break; +} + } + + bool erased = functionsBeingProcessed.erase(&fi); + assert(erased && "Not in set?"); + + return cir::FuncType::get(argTypes, +(resultType ? resultType : builder.getVoidTy()), +fi.isVariadic()); +} + CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { assert(!cir::MissingFeatures::opCallVirtual()); return *this; @@ -35,6 +91,9 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const FunctionType *fnType) { + + RequiredArgs required = RequiredArgs::All; + if (const auto *proto = dyn_cast(fnType)) { if (proto->isVariadic()) cgm.errorNYI("call to variadic function"); @@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, CanQualType retType = fnType->getReturnType() ->getCanonicalTypeUnqualified() .getUnqualifiedType(); - return cgt.arrangeCIRFunctionInfo(retType); + return cgt.arrangeCIRFunctionInfo(retType, {}, required); } const CIRGenFunctionInfo & @@ -71,6 +130,23 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, return builder.createCallOp(callLoc, directFuncOp); } +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) { + SmallVector argTypes; + for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) +argTypes.push_back(fpt->getParamType(i)); + RequiredArgs required = RequiredArgs::forPrototypePlus(fpt); + + CanQualType resultType = fpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, argTypes, required); +} + +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) { + CanQualType resultType = fnpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
[clang] [clang] ownership_returns attribute takes no more than 2 arguments (PR #137897)
https://github.com/el-ev approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/137897 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] ownership_returns attribute takes no more than 2 arguments (PR #137897)
el-ev wrote: ### Merge activity * **Apr 30, 7:27 AM EDT**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/137897). https://github.com/llvm/llvm-project/pull/137897 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] ownership_returns attribute takes no more than 2 arguments (PR #137897)
https://github.com/el-ev closed https://github.com/llvm/llvm-project/pull/137897 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream initial support for union type (PR #137501)
https://github.com/el-ev closed https://github.com/llvm/llvm-project/pull/137501 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Cleanup support for C functions (PR #136854)
@@ -47,18 +98,51 @@ class CIRGenFunctionInfo final // This function has to be CamelCase because llvm::FoldingSet requires so. // NOLINTNEXTLINE(readability-identifier-naming) - static void Profile(llvm::FoldingSetNodeID &id, CanQualType resultType) { + static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required, + CanQualType resultType, + llvm::ArrayRef argTypes) { +id.AddBoolean(required.getOpaqueData()); resultType.Profile(id); +for (const auto &arg : argTypes) + arg.Profile(id); } - void Profile(llvm::FoldingSetNodeID &id) { getReturnType().Profile(id); } + // NOLINTNEXTLINE(readability-identifier-naming) + void Profile(llvm::FoldingSetNodeID &id) { +id.AddBoolean(required.getOpaqueData()); +getReturnType().Profile(id); +for (const auto &i : arguments()) el-ev wrote: Yes. https://github.com/llvm/llvm-project/pull/136854 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Cleanup support for C functions (PR #136854)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/136854 >From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Wed, 23 Apr 2025 20:23:09 +0800 Subject: [PATCH 1/2] [CIR] Cleanup support for C functions --- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 82 +++- clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 37 - clang/lib/CIR/CodeGen/CIRGenTypes.h| 12 ++- clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 ++- clang/test/CIR/CodeGen/basic.c | 13 7 files changed, 232 insertions(+), 29 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 69266f79a88a5..b223bc494f928 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -13,20 +13,76 @@ #include "CIRGenCall.h" #include "CIRGenFunction.h" +#include "CIRGenFunctionInfo.h" #include "clang/CIR/MissingFeatures.h" using namespace clang; using namespace clang::CIRGen; -CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) { - void *buffer = operator new(totalSizeToAlloc(1)); +CIRGenFunctionInfo * +CIRGenFunctionInfo::create(CanQualType resultType, + llvm::ArrayRef argTypes, + RequiredArgs required) { + void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1)); CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo(); + + fi->required = required; + fi->numArgs = argTypes.size(); fi->getArgsBuffer()[0].type = resultType; + for (unsigned i = 0; i < argTypes.size(); ++i) +fi->getArgsBuffer()[i + 1].type = argTypes[i]; return fi; } +cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) { + bool inserted = functionsBeingProcessed.insert(&fi).second; + assert(inserted && "Recursively being processed?"); + + mlir::Type resultType = nullptr; + const cir::ABIArgInfo &retAI = fi.getReturnInfo(); + + switch (retAI.getKind()) { + case cir::ABIArgInfo::Ignore: +// TODO(CIR): This should probably be the None type from the builtin +// dialect. +resultType = nullptr; +break; + + case cir::ABIArgInfo::Direct: +resultType = retAI.getCoerceToType(); +break; + + default: +assert(false && "NYI"); + } + + SmallVector argTypes; + unsigned argNo = 0; + CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(), + ie = it + fi.getNumRequiredArgs(); + for (; it != ie; ++it, ++argNo) { +const auto &argInfo = it->info; + +switch (argInfo.getKind()) { +default: + llvm_unreachable("NYI"); +case cir::ABIArgInfo::Direct: + mlir::Type argType = argInfo.getCoerceToType(); + argTypes.push_back(argType); + break; +} + } + + bool erased = functionsBeingProcessed.erase(&fi); + assert(erased && "Not in set?"); + + return cir::FuncType::get(argTypes, +(resultType ? resultType : builder.getVoidTy()), +fi.isVariadic()); +} + CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { assert(!cir::MissingFeatures::opCallVirtual()); return *this; @@ -35,6 +91,9 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const { static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const FunctionType *fnType) { + + RequiredArgs required = RequiredArgs::All; + if (const auto *proto = dyn_cast(fnType)) { if (proto->isVariadic()) cgm.errorNYI("call to variadic function"); @@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, CanQualType retType = fnType->getReturnType() ->getCanonicalTypeUnqualified() .getUnqualifiedType(); - return cgt.arrangeCIRFunctionInfo(retType); + return cgt.arrangeCIRFunctionInfo(retType, {}, required); } const CIRGenFunctionInfo & @@ -71,6 +130,23 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, return builder.createCallOp(callLoc, directFuncOp); } +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fpt) { + SmallVector argTypes; + for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) +argTypes.push_back(fpt->getParamType(i)); + RequiredArgs required = RequiredArgs::forPrototypePlus(fpt); + + CanQualType resultType = fpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, argTypes, required); +} + +const CIRGenFunctionInfo & +CIRGenTypes::arrangeFreeFunctionType(CanQual fnpt) { + CanQualType resultType = fnpt->getReturnType().getUnqualifiedType(); + return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));