Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}

mlir::Value VisitFixedPointLiteral(const FixedPointLiteral *E) {
llvm_unreachable("NYI");
return Builder.getConstAPInt(CGF.getLoc(E->getExprLoc()),
convertType(E->getType()), E->getValue());
}
mlir::Value VisitFloatingLiteral(const FloatingLiteral *E) {
mlir::Type Ty = CGF.convertType(E->getType());
Expand Down Expand Up @@ -248,7 +249,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}

mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *E) {
llvm_unreachable("NYI");
return Builder.getConstInt(CGF.getLoc(E->getExprLoc()),
convertType(E->getType()), E->getPackLength());
}
mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *E) {
return CGF.emitPseudoObjectRValue(E).getScalarVal();
Expand Down Expand Up @@ -701,7 +703,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {

// C++
mlir::Value VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) {
llvm_unreachable("NYI");
return emitLoadOfLValue(E);
}
mlir::Value VisitSourceLocExpr(SourceLocExpr *E) { llvm_unreachable("NYI"); }
mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
Expand Down Expand Up @@ -734,10 +736,10 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}
mlir::Value
VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {
llvm_unreachable("NYI");
return Builder.getBool(E->isSatisfied(), CGF.getLoc(E->getExprLoc()));
}
mlir::Value VisitRequiresExpr(const RequiresExpr *E) {
llvm_unreachable("NYI");
return Builder.getBool(E->isSatisfied(), CGF.getLoc(E->getExprLoc()));
}
mlir::Value VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
llvm_unreachable("NYI");
Expand Down
56 changes: 56 additions & 0 deletions clang/test/CIR/CodeGen/concept-specialization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

template <typename T>
concept Integral = __is_integral(T);

template <typename T>
concept Signed = Integral<T> && __is_signed(T);

// Test ConceptSpecializationExpr as a boolean value
bool test_concept_bool() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_concept_boolv
// CHECK: %{{.*}} = cir.const #true
return Integral<int>;
}

bool test_concept_false() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_concept_falsev
// CHECK: %{{.*}} = cir.const #false
return Integral<float>;
}

bool test_concept_compound() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_concept_compoundv
// CHECK: %{{.*}} = cir.const #true
return Signed<int>;
}

bool test_concept_unsigned() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_concept_unsignedv
// CHECK: %{{.*}} = cir.const #false
return Signed<unsigned>;
}

// Test in conditional
int test_concept_in_if() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_concept_in_ifv
if (Integral<int>) {
// CHECK: %{{.*}} = cir.const #true
// CHECK: cir.if %{{.*}} {
return 1;
}
return 0;
}

// Test constexpr variable with concept
constexpr bool is_int_integral = Integral<int>;

int use_constexpr() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}use_constexprv
if (is_int_integral) {
// This should be optimized to a constant true
return 42;
}
return 0;
}
40 changes: 40 additions & 0 deletions clang/test/CIR/CodeGen/fixedpoint-literal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -ffixed-point -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

// Test basic fixed-point literals
void test_short_fract() {
// CHECK: cir.func {{.*}}@test_short_fract
short _Fract sf = 0.5hr;
// CHECK: %{{.*}} = cir.const #cir.int<64> : !s8i

unsigned short _Fract usf = 0.5uhr;
// CHECK: %{{.*}} = cir.const #cir.int<128> : !u8i
}

void test_fract() {
// CHECK: cir.func {{.*}}@test_fract
_Fract f = 0.5r;
// CHECK: %{{.*}} = cir.const #cir.int<16384> : !s16i

unsigned _Fract uf = 0.5ur;
// CHECK: %{{.*}} = cir.const #cir.int<32768> : !u16i
}

void test_long_fract() {
// CHECK: cir.func {{.*}}@test_long_fract
long _Fract lf = 0.5lr;
// CHECK: %{{.*}} = cir.const #cir.int<1073741824> : !s32i
}

void test_accum() {
// CHECK: cir.func {{.*}}@test_accum
short _Accum sa = 0.5hk;
// CHECK: %{{.*}} = cir.const #cir.int<64> : !s16i
}

void test_negative() {
// CHECK: cir.func {{.*}}@test_negative
short _Fract sf = -0.5hr;
// CHECK: %{{.*}} = cir.const #cir.int<64> : !s8i
// CHECK: %{{.*}} = cir.unary(minus, %{{.*}}) : !s8i, !s8i
}
54 changes: 54 additions & 0 deletions clang/test/CIR/CodeGen/materialize-temporary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

// Test MaterializeTemporaryExpr when binding const reference to rvalue
int get_value() { return 42; }

void test_const_ref_binding() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_const_ref_bindingv
const int &x = 5;
// CHECK: %{{.*}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init]
// CHECK: %{{.*}} = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init, const]
// CHECK: cir.scope {
// CHECK: %{{.*}} = cir.const #cir.int<5> : !s32i
// CHECK: cir.store {{.*}} %{{.*}}, %{{.*}} : !s32i, !cir.ptr<!s32i>
// CHECK: }
}

void test_const_ref_expr() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_const_ref_exprv
const int &y = get_value();
// CHECK: %{{.*}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init]
// CHECK: %{{.*}} = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["y", init, const]
// CHECK: cir.scope {
// CHECK: %{{.*}} = cir.call @{{.*}}get_valuev()
// CHECK: }
}

void test_const_ref_arithmetic() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_const_ref_arithmeticv
int a = 10;
const int &z = a + 5;
// CHECK: %{{.*}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init]
// CHECK: %{{.*}} = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["z", init, const]
// CHECK: cir.scope {
// CHECK: %{{.*}} = cir.load {{.*}} %{{.*}}
// CHECK: %{{.*}} = cir.const #cir.int<5> : !s32i
// CHECK: %{{.*}} = cir.binop(add, %{{.*}}, %{{.*}})
// CHECK: }
}

struct S {
int val;
S(int v) : val(v) {}
};

S make_s() { return S(100); }

void test_const_ref_struct() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_const_ref_structv
const S &s = make_s();
// Temporary S object should be materialized
// CHECK: %{{.*}} = cir.alloca {{.*}}, !cir.ptr<{{.*}}rec_S{{.*}}>, ["ref.tmp0"]
// CHECK: %{{.*}} = cir.alloca !cir.ptr<{{.*}}>, !cir.ptr<!cir.ptr<{{.*}}>>, ["s", init, const]
}
75 changes: 75 additions & 0 deletions clang/test/CIR/CodeGen/requires-expr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

// Test RequiresExpr as a boolean expression
bool test_requires_simple() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_requires_simplev
// CHECK: %{{.*}} = cir.const #true
return requires { 1 + 1; };
}

template <typename T>
bool test_requires_param() {
return requires(T t) { t + 1; };
}

bool use_requires_param() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}use_requires_paramv
// Instantiation with int should succeed
return test_requires_param<int>();
// CHECK: cir.call @{{.*}}test_requires_paramIiEbv
}

// Test requires expression with multiple requirements
bool test_requires_multiple() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_requires_multiplev
// CHECK: %{{.*}} = cir.const #true
return requires {
1 + 1;
2 * 2;
};
}

// Test requires expression in if statement
int test_requires_in_if() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_requires_in_ifv
if (requires { 1 + 1; }) {
// CHECK: %{{.*}} = cir.const #true
// CHECK: cir.if %{{.*}} {
return 1;
}
return 0;
}

// Test requires expression that should fail
template <typename T>
bool test_requires_fail() {
return requires { T::nonexistent_member; };
}

bool use_requires_fail() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}use_requires_failv
// Should return false for int (no member named nonexistent_member)
return test_requires_fail<int>();
// CHECK: cir.call @{{.*}}test_requires_failIiEbv
}

// Test nested requires
bool test_nested_requires() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}test_nested_requiresv
// CHECK: %{{.*}} = cir.const #true
return requires {
requires true;
};
}

// Use in constexpr context
constexpr bool can_add_int = requires(int a, int b) { a + b; };

int use_constexpr_requires() {
// CHECK-LABEL: cir.func {{.*}}@{{.*}}use_constexpr_requiresv
if (can_add_int) {
return 42;
}
return 0;
}
36 changes: 36 additions & 0 deletions clang/test/CIR/CodeGen/sizeof-pack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

// Test basic sizeof... on type parameter pack
template<typename ...Types>
int get_num_types(Types...) {
return sizeof...(Types);
}

// CHECK-LABEL: cir.func {{.*}}@{{.*}}get_num_typesIJifdEEiDpT_
// CHECK: %{{.*}} = cir.const #cir.int<3> : !u64i
// CHECK: %{{.*}} = cir.cast integral %{{.*}} : !u64i -> !s32i

template int get_num_types(int, float, double);

// Test sizeof... with empty pack
template<typename ...Types>
int get_num_empty(Types...) {
return sizeof...(Types);
}

// CHECK-LABEL: cir.func {{.*}}@{{.*}}get_num_emptyIJEEiDpT_
// CHECK: %{{.*}} = cir.const #cir.int<0> : !u64i

template int get_num_empty();

// Test sizeof... on non-type parameter pack
template<int... Vals>
int count_values() {
return sizeof...(Vals);
}

// CHECK-LABEL: cir.func {{.*}}@{{.*}}count_valuesIJLi1ELi2ELi3ELi4ELi5EEEiv
// CHECK: %{{.*}} = cir.const #cir.int<5> : !u64i

template int count_values<1, 2, 3, 4, 5>();
Loading