[CIR] Upstream zero init for global variables (#133100)

This change adds zero initialization for global variables
This commit is contained in:
Amr Hesham 2025-03-31 19:41:29 +02:00 committed by GitHub
parent 7eb99b8599
commit 143c37123b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 92 additions and 67 deletions

View File

@ -67,6 +67,30 @@ public:
return create<cir::ConstantOp>(loc, attr.getType(), attr);
}
mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
return getConstPtrAttr(t, 0);
}
mlir::TypedAttr getZeroAttr(mlir::Type t) {
return cir::ZeroAttr::get(getContext(), t);
}
mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
if (mlir::isa<cir::IntType>(ty))
return cir::IntAttr::get(ty, 0);
if (cir::isAnyFloatingPointType(ty))
return cir::FPAttr::getZero(ty);
if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
return getZeroAttr(arrTy);
if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
return getConstNullPtrAttr(ptrTy);
if (mlir::isa<cir::BoolType>(ty)) {
return getCIRBoolAttr(false);
}
llvm_unreachable("Zero initializer for given type is NYI");
}
cir::ConstantOp getBool(bool state, mlir::Location loc) {
return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
}

View File

@ -140,17 +140,20 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
// certain constant expressions is implemented for now.
const VarDecl *initDecl;
const Expr *initExpr = vd->getAnyInitializer(initDecl);
mlir::Attribute initializer;
if (initExpr) {
mlir::Attribute initializer;
if (APValue *value = initDecl->evaluateValue()) {
ConstantEmitter emitter(*this);
initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
} else {
errorNYI(initExpr->getSourceRange(), "non-constant initializer");
}
varOp.setInitialValueAttr(initializer);
} else {
initializer = builder.getZeroInitAttr(convertType(astTy));
}
varOp.setInitialValueAttr(initializer);
// Set CIR's linkage type as appropriate.
cir::GlobalLinkageKind linkage =
getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);

View File

@ -1,16 +1,16 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
int a[10];
// CHECK: cir.global external @a : !cir.array<!s32i x 10>
// CHECK: cir.global external @a = #cir.zero : !cir.array<!s32i x 10>
int aa[10][5];
// CHECK: cir.global external @aa : !cir.array<!cir.array<!s32i x 5> x 10>
// CHECK: cir.global external @aa = #cir.zero : !cir.array<!cir.array<!s32i x 5> x 10>
extern int b[10];
// CHECK: cir.global external @b : !cir.array<!s32i x 10>
// CHECK: cir.global external @b = #cir.zero : !cir.array<!s32i x 10>
extern int bb[10][5];
// CHECK: cir.global external @bb : !cir.array<!cir.array<!s32i x 5> x 10>
// CHECK: cir.global external @bb = #cir.zero : !cir.array<!cir.array<!s32i x 5> x 10>
int c[10] = {};
// CHECK: cir.global external @c = #cir.zero : !cir.array<!s32i x 10>

View File

@ -1,16 +1,16 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - 2>&1 | FileCheck %s
int a[10];
// CHECK: @a = external dso_local global [10 x i32]
// CHECK: @a = dso_local global [10 x i32] zeroinitializer
int aa[10][5];
// CHECK: @aa = external dso_local global [10 x [5 x i32]]
// CHECK: @aa = dso_local global [10 x [5 x i32]] zeroinitializer
extern int b[10];
// CHECK: @b = external dso_local global [10 x i32]
// CHECK: @b = dso_local global [10 x i32] zeroinitializer
extern int bb[10][5];
// CHECK: @bb = external dso_local global [10 x [5 x i32]]
// CHECK: @bb = dso_local global [10 x [5 x i32]] zeroinitializer
int c[10] = {};
// CHECK: @c = dso_local global [10 x i32] zeroinitializer

View File

@ -1,21 +1,19 @@
// Global variables of intergal types
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
// Note: Currently unsupported features include default zero-initialization
// and alignment. The fact that "external" is only printed for globals
// without an initializer is a quirk of the LLVM AsmWriter.
// Note: Currently unsupported features include alignment..
char c;
// CHECK: @c = external dso_local global i8
// CHECK: @c = dso_local global i8 0
signed char sc;
// CHECK: @sc = external dso_local global i8
// CHECK: @sc = dso_local global i8 0
unsigned char uc;
// CHECK: @uc = external dso_local global i8
// CHECK: @uc = dso_local global i8 0
short ss;
// CHECK: @ss = external dso_local global i16
// CHECK: @ss = dso_local global i16 0
unsigned short us = 100;
// CHECK: @us = dso_local global i16 100
@ -24,82 +22,82 @@ int si = 42;
// CHECK: @si = dso_local global i32 42
unsigned ui;
// CHECK: @ui = external dso_local global i32
// CHECK: @ui = dso_local global i32 0
long sl;
// CHECK: @sl = external dso_local global i64
// CHECK: @sl = dso_local global i64 0
unsigned long ul;
// CHECK: @ul = external dso_local global i64
// CHECK: @ul = dso_local global i64 0
long long sll;
// CHECK: @sll = external dso_local global i64
// CHECK: @sll = dso_local global i64 0
unsigned long long ull = 123456;
// CHECK: @ull = dso_local global i64 123456
__int128 s128;
// CHECK: @s128 = external dso_local global i128
// CHECK: @s128 = dso_local global i128 0
unsigned __int128 u128;
// CHECK: @u128 = external dso_local global i128
// CHECK: @u128 = dso_local global i128 0
wchar_t wc;
// CHECK: @wc = external dso_local global i32
// CHECK: @wc = dso_local global i32 0
char8_t c8;
// CHECK: @c8 = external dso_local global i8
// CHECK: @c8 = dso_local global i8 0
char16_t c16;
// CHECK: @c16 = external dso_local global i16
// CHECK: @c16 = dso_local global i16 0
char32_t c32;
// CHECK: @c32 = external dso_local global i32
// CHECK: @c32 = dso_local global i32 0
_BitInt(20) sb20;
// CHECK: @sb20 = external dso_local global i20
// CHECK: @sb20 = dso_local global i20 0
unsigned _BitInt(48) ub48;
// CHECK: @ub48 = external dso_local global i48
// CHECK: @ub48 = dso_local global i48 0
bool boolfalse = false;
// CHECK: @boolfalse = dso_local global i8 0
_Float16 f16;
// CHECK: @f16 = external dso_local global half
// CHECK: @f16 = dso_local global half
__bf16 bf16;
// CHECK: @bf16 = external dso_local global bfloat
// CHECK: @bf16 = dso_local global bfloat
float f;
// CHECK: @f = external dso_local global float
// CHECK: @f = dso_local global float 0.000000e+00
double d = 1.25;
// CHECK: @d = dso_local global double 1.250000e+00
long double ld;
// CHECK: @ld = external dso_local global x86_fp80
// CHECK: @ld = dso_local global x86_fp80 0xK00
__float128 f128;
// CHECK: @f128 = external dso_local global fp128
// CHECK: @f128 = dso_local global fp128 0xL00
void *vp;
// CHECK: @vp = external dso_local global ptr{{$}}
// CHECK: @vp = dso_local global ptr null
int *ip = 0;
// CHECK: @ip = dso_local global ptr null
double *dp;
// CHECK: @dp = external dso_local global ptr{{$}}
// CHECK: @dp = dso_local global ptr null
char **cpp;
// CHECK: @cpp = external dso_local global ptr{{$}}
// CHECK: @cpp = dso_local global ptr null
void (*fp)();
// CHECK: @fp = external dso_local global ptr{{$}}
// CHECK: @fp = dso_local global ptr null
int (*fpii)(int) = 0;
// CHECK: @fpii = dso_local global ptr null
void (*fpvar)(int, ...);
// CHECK: @fpvar = external dso_local global ptr{{$}}
// CHECK: @fpvar = dso_local global ptr null

View File

@ -3,7 +3,7 @@
int a;
// CHECK: @a = external dso_local global i32
// CHECK: @a = dso_local global i32 0
int b = 2;

View File

@ -2,16 +2,16 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s
char c;
// CHECK: cir.global external @c : !s8i
// CHECK: cir.global external @c = #cir.int<0> : !s8i
signed char sc;
// CHECK: cir.global external @sc : !s8i
// CHECK: cir.global external @sc = #cir.int<0> : !s8i
unsigned char uc;
// CHECK: cir.global external @uc : !u8i
// CHECK: cir.global external @uc = #cir.int<0> : !u8i
short ss;
// CHECK: cir.global external @ss : !s16i
// CHECK: cir.global external @ss = #cir.int<0> : !s16i
unsigned short us = 100;
// CHECK: cir.global external @us = #cir.int<100> : !u16i
@ -20,82 +20,82 @@ int si = 42;
// CHECK: cir.global external @si = #cir.int<42> : !s32i
unsigned ui;
// CHECK: cir.global external @ui : !u32i
// CHECK: cir.global external @ui = #cir.int<0> : !u32i
long sl;
// CHECK: cir.global external @sl : !s64i
// CHECK: cir.global external @sl = #cir.int<0> : !s64i
unsigned long ul;
// CHECK: cir.global external @ul : !u64i
// CHECK: cir.global external @ul = #cir.int<0> : !u64i
long long sll;
// CHECK: cir.global external @sll : !s64i
// CHECK: cir.global external @sll = #cir.int<0> : !s64i
unsigned long long ull = 123456;
// CHECK: cir.global external @ull = #cir.int<123456> : !u64i
__int128 s128;
// CHECK: cir.global external @s128 : !s128i
// CHECK: cir.global external @s128 = #cir.int<0> : !s128i
unsigned __int128 u128;
// CHECK: cir.global external @u128 : !u128i
// CHECK: cir.global external @u128 = #cir.int<0> : !u128i
wchar_t wc;
// CHECK: cir.global external @wc : !s32i
// CHECK: cir.global external @wc = #cir.int<0> : !s32i
char8_t c8;
// CHECK: cir.global external @c8 : !u8i
// CHECK: cir.global external @c8 = #cir.int<0> : !u8i
char16_t c16;
// CHECK: cir.global external @c16 : !u16i
// CHECK: cir.global external @c16 = #cir.int<0> : !u16i
char32_t c32;
// CHECK: cir.global external @c32 : !u32i
// CHECK: cir.global external @c32 = #cir.int<0> : !u32i
_BitInt(20) sb20;
// CHECK: cir.global external @sb20 : !cir.int<s, 20>
// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20>
unsigned _BitInt(48) ub48;
// CHECK: cir.global external @ub48 : !cir.int<u, 48>
// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48>
bool boolfalse = false;
// CHECK: cir.global external @boolfalse = #false
_Float16 f16;
// CHECK: cir.global external @f16 : !cir.f16
// CHECK: cir.global external @f16 = #cir.fp<0.000000e+00> : !cir.f16
__bf16 bf16;
// CHECK: cir.global external @bf16 : !cir.bf16
// CHECK: cir.global external @bf16 = #cir.fp<0.000000e+00> : !cir.bf16
float f;
// CHECK: cir.global external @f : !cir.float
// CHECK: cir.global external @f = #cir.fp<0.000000e+00> : !cir.float
double d = 1.25;
// CHECK: cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
long double ld;
// CHECK: cir.global external @ld : !cir.long_double<!cir.f80>
// CHECK: cir.global external @ld = #cir.fp<0.000000e+00> : !cir.long_double<!cir.f80>
__float128 f128;
// CHECK: cir.global external @f128 : !cir.f128
// CHECK: cir.global external @f128 = #cir.fp<0.000000e+00> : !cir.f128
void *vp;
// CHECK: cir.global external @vp : !cir.ptr<!void>
// CHECK: cir.global external @vp = #cir.ptr<null> : !cir.ptr<!void>
int *ip = 0;
// CHECK: cir.global external @ip = #cir.ptr<null> : !cir.ptr<!s32i>
double *dp;
// CHECK: cir.global external @dp : !cir.ptr<!cir.double>
// CHECK: cir.global external @dp = #cir.ptr<null> : !cir.ptr<!cir.double>
char **cpp;
// CHECK: cir.global external @cpp : !cir.ptr<!cir.ptr<!s8i>>
// CHECK: cir.global external @cpp = #cir.ptr<null> : !cir.ptr<!cir.ptr<!s8i>>
void (*fp)();
// CHECK: cir.global external @fp : !cir.ptr<!cir.func<()>>
// CHECK: cir.global external @fp = #cir.ptr<null> : !cir.ptr<!cir.func<()>>
int (*fpii)(int) = 0;
// CHECK: cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i) -> !s32i>>
void (*fpvar)(int, ...);
// CHECK: cir.global external @fpvar : !cir.ptr<!cir.func<(!s32i, ...)>>
// CHECK: cir.global external @fpvar = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i, ...)>>