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
13 changes: 12 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "Address.h"
#include "CIRGenCstEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
#include "CIRGenOpenMPRuntime.h"
Expand Down Expand Up @@ -705,7 +706,17 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
mlir::Value VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) {
return emitLoadOfLValue(E);
}
mlir::Value VisitSourceLocExpr(SourceLocExpr *E) { llvm_unreachable("NYI"); }
mlir::Value VisitSourceLocExpr(SourceLocExpr *E) {
auto &Ctx = CGF.getContext();
APValue Evaluated =
E->EvaluateInContext(Ctx, CGF.CurSourceLocExprScope.getDefaultExpr());
auto C = ConstantEmitter(CGF).emitAbstract(E->getLocation(), Evaluated,
E->getType());
mlir::TypedAttr typedAttr = mlir::dyn_cast_or_null<mlir::TypedAttr>(C);
assert(typedAttr && "SourceLocExpr must produce a typed constant");
return cir::ConstantOp::create(Builder, CGF.getLoc(E->getExprLoc()),
typedAttr);
}
mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
CIRGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
return Visit(DAE->getExpr());
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1845,7 +1845,10 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
// Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
// we need to do that explicitly.
std::string uniqueName = getUniqueGlobalName(globalVariableName.str());
auto loc = getLoc(s->getSourceRange());
// Synthetic string literals (e.g., from SourceLocExpr) may not have valid
// source locations. Use unknown location in those cases.
auto loc = s->getBeginLoc().isValid() ? getLoc(s->getSourceRange())
: builder.getUnknownLoc();
auto typedC = llvm::dyn_cast<mlir::TypedAttr>(c);
if (!typedC)
llvm_unreachable("this should never be untyped at this point");
Expand Down
126 changes: 126 additions & 0 deletions clang/test/CIR/CodeGen/source-loc-expr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm %s -o %t.og.ll
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.og.ll %s

// Test in global context
#line 100 "test_file.cpp"
int global_line = __builtin_LINE();
// CIR: cir.global external @global_line = #cir.int<100> : !s32i
// LLVM: @global_line{{.*}} = global i32 100
// OGCG: @global_line{{.*}} = global i32 100

#line 15 "clang/test/CIR/CodeGen/source-loc-expr.cpp"
// Test __builtin_LINE
int test_builtin_LINE() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_builtin_LINE
// CIR: %{{.*}} = cir.const #cir.int<25> : !u32i

// LLVM-LABEL: @{{.*}}test_builtin_LINE
// LLVM: store i32 25

// OGCG-LABEL: @{{.*}}test_builtin_LINE
// OGCG: ret i32 25
return __builtin_LINE();
}

// Test __builtin_FILE
const char* test_builtin_FILE() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_builtin_FILE
// CIR: %{{.*}} = cir.const #cir.global_view<@".str{{.*}}"> : !cir.ptr<!s8i>

// LLVM-LABEL: @{{.*}}test_builtin_FILE
// LLVM: store ptr @.str

// OGCG-LABEL: @{{.*}}test_builtin_FILE
// OGCG: ret ptr @.str
return __builtin_FILE();
}

// Test __builtin_FUNCTION
const char* test_builtin_FUNCTION() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_builtin_FUNCTION
// CIR: %{{.*}} = cir.const #cir.global_view<@".str{{.*}}"> : !cir.ptr<!s8i>

// LLVM-LABEL: @{{.*}}test_builtin_FUNCTION
// LLVM: store ptr @.str

// OGCG-LABEL: @{{.*}}test_builtin_FUNCTION
// OGCG: ret ptr @.str
return __builtin_FUNCTION();
}

// Test __builtin_COLUMN
int test_builtin_COLUMN() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_builtin_COLUMN
// The column number is the position of '__builtin_COLUMN'
// CIR: %{{.*}} = cir.const #cir.int<10> : !u32i

// LLVM-LABEL: @{{.*}}test_builtin_COLUMN
// LLVM: store i32 10

// OGCG-LABEL: @{{.*}}test_builtin_COLUMN
// OGCG: ret i32 10
return __builtin_COLUMN();
}

// Test default argument
int get_line(int l = __builtin_LINE()) {
return l;
}

void test_default_arg() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_default_arg
// The LINE should be from the call site, not the default argument definition
#line 111
int x = get_line();
// CIR: %{{.*}} = cir.const #cir.int<111> : !u32i
// CIR: %{{.*}} = cir.call @{{.*}}get_line{{.*}}({{.*}}) :

// LLVM-LABEL: @{{.*}}test_default_arg
// LLVM: call{{.*}} i32 @{{.*}}get_line{{.*}}(i32 111)

// OGCG-LABEL: @{{.*}}test_default_arg
// OGCG: call{{.*}} i32 @{{.*}}get_line{{.*}}(i32 {{.*}} 111)
}

#line 200 "lambda-test.cpp"
// Test in lambda (this tests that source location correctly captures context)
void test_in_lambda() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_in_lambda
auto lambda = []() {
return __builtin_LINE();
};
int x = lambda();

// LLVM-LABEL: @{{.*}}test_in_lambda
// LLVM: call{{.*}} i32 @{{.*}}

// OGCG-LABEL: @{{.*}}test_in_lambda
// OGCG: call{{.*}} i32 @{{.*}}
}

#line 214 "combined-test.cpp"
// Test multiple builtins in one expression
void test_combined() {
// CIR-LABEL: cir.func {{.*}}@{{.*}}test_combined
const char* file = __builtin_FILE();
int line = __builtin_LINE();
const char* func = __builtin_FUNCTION();
// All should produce constants
// CIR: cir.const
// CIR: cir.const
// CIR: cir.const

// LLVM-LABEL: @{{.*}}test_combined
// LLVM: store ptr @.str
// LLVM: store i32 218
// LLVM: store ptr @.str

// OGCG-LABEL: @{{.*}}test_combined
// OGCG: store ptr @.str
// OGCG: store i32 218
// OGCG: store ptr @.str
}