https://github.com/adams381 created https://github.com/llvm/llvm-project/pull/170915
This PR migrates the Function Argument Demotion feature from the incubator repository to upstream. The feature handles K&R-style function parameters that are promoted (e.g., short->int, float->double) and demotes them back to their declared types. ## Changes - Add emitArgumentDemotion helper function for type demotion - Create emitFunctionProlog function to handle function prologue setup (addresses existing TODO to move parameter handling logic) - Move parameter handling logic into emitFunctionProlog - Add test case kr-func-promote.c to verify the feature Tested: All CIR tests pass (320/321, 99.69%). The one unsupported test is an expected failure. >From 4f400f1cf35c8db55c43e3e3d8d422d8fe5be856 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Fri, 5 Dec 2025 10:26:19 -0800 Subject: [PATCH] Add Function Argument Demotion support This commit migrates the Function Argument Demotion feature from the incubator repository to upstream. The feature handles K&R-style function parameters that are promoted (e.g., short->int, float->double) and demotes them back to their declared types. Changes: - Add emitArgumentDemotion helper function for type demotion - Create emitFunctionProlog function to handle function prologue setup (addresses existing TODO to move parameter handling logic) - Move parameter handling logic into emitFunctionProlog - Add test case kr-func-promote.c to verify the feature Tested: All CIR tests pass (320/321, 99.69%). The one unsupported test is an expected failure. --- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 62 +++++++++++++++++------- clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 ++ clang/test/CIR/CodeGen/kr-func-promote.c | 13 +++++ 3 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 clang/test/CIR/CodeGen/kr-func-promote.c diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 5d5209b9ffb60..10c4a16fb9687 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -412,28 +412,30 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() { (void)emitReturn(localScope->endLoc); } -void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, - cir::FuncOp fn, cir::FuncType funcType, - FunctionArgList args, SourceLocation loc, - SourceLocation startLoc) { - assert(!curFn && - "CIRGenFunction can only be used for one function at a time"); +/// An argument came in as a promoted argument; demote it back to its +/// declared type. +static mlir::Value emitArgumentDemotion(CIRGenFunction &cgf, const VarDecl *var, + mlir::Value value) { + mlir::Type ty = cgf.convertType(var->getType()); - curFn = fn; + // This can happen with promotions that actually don't change the + // underlying type, like the enum promotions. + if (value.getType() == ty) + return value; - const Decl *d = gd.getDecl(); - - didCallStackSave = false; - curCodeDecl = d; - const auto *fd = dyn_cast_or_null<FunctionDecl>(d); - curFuncDecl = d->getNonClosureContext(); + assert((mlir::isa<cir::IntType>(ty) || cir::isAnyFloatingPointType(ty)) && + "unexpected promotion type"); - prologueCleanupDepth = ehStack.stable_begin(); + if (mlir::isa<cir::IntType>(ty)) + return cgf.getBuilder().CIRBaseBuilderTy::createIntCast(value, ty); - mlir::Block *entryBB = &fn.getBlocks().front(); - builder.setInsertionPointToStart(entryBB); + return cgf.getBuilder().CIRBaseBuilderTy::createCast(cir::CastKind::floating, + value, ty); +} - // TODO(cir): this should live in `emitFunctionProlog +void CIRGenFunction::emitFunctionProlog(const FunctionArgList &args, + mlir::Block *entryBB, + const FunctionDecl *fd) { // Declare all the function arguments in the symbol table. for (const auto nameValue : llvm::zip(args, entryBB->getArguments())) { const VarDecl *paramVar = std::get<0>(nameValue); @@ -456,7 +458,7 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, cast<ParmVarDecl>(paramVar)->isKNRPromoted(); assert(!cir::MissingFeatures::constructABIArgDirectExtend()); if (isPromoted) - cgm.errorNYI(fd->getSourceRange(), "Function argument demotion"); + paramVal = emitArgumentDemotion(*this, paramVar, paramVal); // Location of the store to the param storage tracked as beginning of // the function body. @@ -464,6 +466,30 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal); } assert(builder.getInsertionBlock() && "Should be valid"); +} + +void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, + cir::FuncOp fn, cir::FuncType funcType, + FunctionArgList args, SourceLocation loc, + SourceLocation startLoc) { + assert(!curFn && + "CIRGenFunction can only be used for one function at a time"); + + curFn = fn; + + const Decl *d = gd.getDecl(); + + didCallStackSave = false; + curCodeDecl = d; + const auto *fd = dyn_cast_or_null<FunctionDecl>(d); + curFuncDecl = d->getNonClosureContext(); + + prologueCleanupDepth = ehStack.stable_begin(); + + mlir::Block *entryBB = &fn.getBlocks().front(); + builder.setInsertionPointToStart(entryBB); + + emitFunctionProlog(args, entryBB, fd); // When the current function is not void, create an address to store the // result value. diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index e5cecaa573a6e..7ce7998825b18 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -901,6 +901,10 @@ class CIRGenFunction : public CIRGenTypeCache { clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args); + /// Emit the function prologue: declare function arguments in the symbol table. + void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB, + const FunctionDecl *fd); + /// Emit code for the start of a function. /// \param loc The location to be associated with the function. /// \param startLoc The location of the function body. diff --git a/clang/test/CIR/CodeGen/kr-func-promote.c b/clang/test/CIR/CodeGen/kr-func-promote.c new file mode 100644 index 0000000000000..f34e11ce3e9e1 --- /dev/null +++ b/clang/test/CIR/CodeGen/kr-func-promote.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s + +// CHECK: cir.func {{.*}}@foo(%arg0: !s32i +// CHECK: %0 = cir.alloca !s16i, !cir.ptr<!s16i>, ["x", init] +// CHECK: %1 = cir.cast integral %arg0 : !s32i -> !s16i +// CHECK: cir.store %1, %0 : !s16i, !cir.ptr<!s16i> +void foo(x) short x; {} + +// CHECK: cir.func no_proto dso_local @bar(%arg0: !cir.double +// CHECK: %0 = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["f", init] +// CHECK: %1 = cir.cast floating %arg0 : !cir.double -> !cir.float +// CHECK: cir.store %1, %0 : !cir.float, !cir.ptr<!cir.float> +void bar(f) float f; {} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
