Skip to content

Commit 9fac59a

Browse files
authored
[HLSL] Allow arrays to be returned by value in HLSL (#127896)
Enable Arrays to be returned in HLSL, and a test for this. Closes #126568
1 parent 0182b23 commit 9fac59a

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

clang/include/clang/Basic/LangOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,8 @@ class LangOptions : public LangOptionsBase {
816816
VisibilityForcedKinds::ForceHidden;
817817
}
818818

819+
bool allowArrayReturnTypes() const { return HLSL; }
820+
819821
/// Remap path prefix according to -fmacro-prefix-path option.
820822
void remapPathPrefix(SmallVectorImpl<char> &Path) const;
821823

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20679,7 +20679,8 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
2067920679
const FunctionType *FnType = CalleeType->castAs<FunctionType>();
2068020680

2068120681
// Verify that this is a legal result type of a function.
20682-
if (DestType->isArrayType() || DestType->isFunctionType()) {
20682+
if ((DestType->isArrayType() && !S.getLangOpts().allowArrayReturnTypes()) ||
20683+
DestType->isFunctionType()) {
2068320684
unsigned diagID = diag::err_func_returning_array_function;
2068420685
if (Kind == FK_BlockPointer)
2068520686
diagID = diag::err_block_returning_array_function;

clang/lib/Sema/SemaType.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,7 +2530,8 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols,
25302530
}
25312531

25322532
bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
2533-
if (T->isArrayType() || T->isFunctionType()) {
2533+
if ((T->isArrayType() && !getLangOpts().allowArrayReturnTypes()) ||
2534+
T->isFunctionType()) {
25342535
Diag(Loc, diag::err_func_returning_array_function)
25352536
<< T->isFunctionType() << T;
25362537
return true;
@@ -4934,7 +4935,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
49344935

49354936
// C99 6.7.5.3p1: The return type may not be a function or array type.
49364937
// For conversion functions, we'll diagnose this particular error later.
4937-
if (!D.isInvalidType() && (T->isArrayType() || T->isFunctionType()) &&
4938+
if (!D.isInvalidType() &&
4939+
((T->isArrayType() && !S.getLangOpts().allowArrayReturnTypes()) ||
4940+
T->isFunctionType()) &&
49384941
(D.getName().getKind() !=
49394942
UnqualifiedIdKind::IK_ConversionFunctionId)) {
49404943
unsigned diagID = diag::err_func_returning_array_function;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
2+
3+
typedef int Foo[2];
4+
5+
// CHECK-LABEL: define void {{.*}}boop{{.*}}(ptr dead_on_unwind noalias writable sret([2 x i32]) align 4 %agg.result)
6+
// CHECK: [[G:%.*]] = alloca [2 x i32], align 4
7+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[G]], ptr align 4 {{.*}}, i32 8, i1 false)
8+
// CHECK-NEXT: [[AIB:%.*]] = getelementptr inbounds [2 x i32], ptr %agg.result, i32 0, i32 0
9+
// CHECK-NEXT: br label %arrayinit.body
10+
// CHECK: arrayinit.body:
11+
// CHECK-NEXT: [[AII:%.*]] = phi i32 [ 0, %entry ], [ %arrayinit.next, %arrayinit.body ]
12+
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds i32, ptr [[AIB]], i32 [[AII]]
13+
// CHECK-NEXT: [[AI:%.*]] = getelementptr inbounds nuw [2 x i32], ptr [[G]], i32 0, i32 [[AII]]
14+
// CHECK-NEXT: [[Y:%.*]] = load i32, ptr [[AI]], align 4
15+
// CHECK-NEXT: store i32 [[Y]], ptr [[X]], align 4
16+
// CHECK-NEXT: [[AIN:%.*]] = add nuw i32 [[AII]], 1
17+
// CHECK-NEXT: [[AID:%.*]] = icmp eq i32 [[AIN]], 2
18+
// CHECK-NEXT: br i1 [[AID]], label %arrayinit.end, label %arrayinit.body
19+
// CHECK: arrayinit.end:
20+
// CHECK-NEXT: ret void
21+
export Foo boop() {
22+
Foo G = {1,2};
23+
return G;
24+
}
25+
26+
// CHECK-LABEL: define void {{.*}}foo{{.*}}(ptr dead_on_unwind noalias writable sret([2 x i32]) align 4 %agg.result)
27+
// CHECK: store i32 1, ptr %agg.result, align 4
28+
// CHECK-NEXT: [[E:%.*]] = getelementptr inbounds i32, ptr %agg.result, i32 1
29+
// CHECK-NEXT: store i32 2, ptr [[E]], align 4
30+
// CHECK-NEXT: ret void
31+
export int foo()[2] {
32+
return {1,2};
33+
}

0 commit comments

Comments
 (0)