Skip to content
Merged
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
37 changes: 37 additions & 0 deletions lib/IRGen/GenConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,41 @@ llvm::Constant *irgen::emitConstantInt(IRGenModule &IGM,
return llvm::ConstantInt::get(IGM.getLLVMContext(), value);
}

llvm::Constant *irgen::emitConstantZero(IRGenModule &IGM, BuiltinInst *BI) {
assert(IGM.getSILModule().getBuiltinInfo(BI->getName()).ID ==
BuiltinValueKind::ZeroInitializer);

auto helper = [&](CanType astType) -> llvm::Constant * {
if (auto type = astType->getAs<BuiltinIntegerType>()) {
APInt zero(type->getWidth().getLeastWidth(), 0);
return llvm::ConstantInt::get(IGM.getLLVMContext(), zero);
}

if (auto type = astType->getAs<BuiltinFloatType>()) {
const llvm::fltSemantics *sema = nullptr;
switch (type->getFPKind()) {
case BuiltinFloatType::IEEE16: sema = &APFloat::IEEEhalf(); break;
case BuiltinFloatType::IEEE32: sema = &APFloat::IEEEsingle(); break;
case BuiltinFloatType::IEEE64: sema = &APFloat::IEEEdouble(); break;
case BuiltinFloatType::IEEE80: sema = &APFloat::x87DoubleExtended(); break;
case BuiltinFloatType::IEEE128: sema = &APFloat::IEEEquad(); break;
case BuiltinFloatType::PPC128: sema = &APFloat::PPCDoubleDouble(); break;
}
auto zero = APFloat::getZero(*sema);
return llvm::ConstantFP::get(IGM.getLLVMContext(), zero);
}

llvm_unreachable("SIL allowed an unknown type?");
};

if (auto vector = BI->getType().getAs<BuiltinVectorType>()) {
auto zero = helper(vector.getElementType());
return llvm::ConstantVector::getSplat(vector->getNumElements(), zero);
}

return helper(BI->getType().getASTType());
}

llvm::Constant *irgen::emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI) {
return llvm::ConstantFP::get(IGM.getLLVMContext(), FLI->getValue());
}
Expand Down Expand Up @@ -94,6 +129,8 @@ static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
return emitAddrOfConstantString(IGM, SLI);
} else if (auto *BI = dyn_cast<BuiltinInst>(operand)) {
switch (IGM.getSILModule().getBuiltinInfo(BI->getName()).ID) {
case BuiltinValueKind::ZeroInitializer:
return emitConstantZero(IGM, BI);
case BuiltinValueKind::PtrToInt: {
llvm::Constant *ptr = emitConstantValue(IGM, BI->getArguments()[0]);
return llvm::ConstantExpr::getPtrToInt(ptr, IGM.IntPtrTy);
Expand Down
3 changes: 3 additions & 0 deletions lib/IRGen/GenConstant.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ namespace irgen {
/// Construct a ConstantInt from an IntegerLiteralInst.
llvm::Constant *emitConstantInt(IRGenModule &IGM, IntegerLiteralInst *ILI);

/// Construct a zero from a zero intializer BuiltinInst.
llvm::Constant *emitConstantZero(IRGenModule &IGM, BuiltinInst *Bi);

/// Construct a ConstantFP from a FloatLiteralInst.
llvm::Constant *emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI);

Expand Down
6 changes: 6 additions & 0 deletions lib/SIL/IR/SILGlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ bool SILGlobalVariable::isValidStaticInitializerInst(const SILInstruction *I,
case SILInstructionKind::BuiltinInst: {
auto *bi = cast<BuiltinInst>(I);
switch (M.getBuiltinInfo(bi->getName()).ID) {
case BuiltinValueKind::ZeroInitializer: {
auto type = bi->getType().getASTType();
if (auto vector = dyn_cast<BuiltinVectorType>(type))
type = vector.getElementType();
return isa<BuiltinIntegerType>(type) || isa<BuiltinFloatType>(type);
}
case BuiltinValueKind::PtrToInt:
if (isa<LiteralInst>(bi->getArguments()[0]))
return true;
Expand Down
44 changes: 44 additions & 0 deletions test/SILOptimizer/zeroInitializer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %target-swift-frontend -O -parse-stdlib -emit-ir -module-name ZeroInit -verify %s | %FileCheck %s

import Swift

@frozen
public struct TestInt {
@usableFromInline
var _value : Builtin.Int32
@_transparent
public init() {
_value = Builtin.zeroInitializer()
}
}

@frozen
public struct TestFloat {
@usableFromInline
var _value : Builtin.FPIEEE32
@_transparent
public init() {
_value = Builtin.zeroInitializer()
}
}

@frozen
public struct TestVector {
@usableFromInline
var _value : Builtin.Vec4xFPIEEE32
@_transparent
public init() {
_value = Builtin.zeroInitializer()
}
}

public struct Foo {
public static var x : TestInt = TestInt()
public static var y : TestFloat = TestFloat()
public static var z : TestVector = TestVector()
}

// CHECK: @"$s8ZeroInit3FooV1xAA7TestIntVvpZ" ={{.*}} global %T8ZeroInit7TestIntV zeroinitializer
// CHECK: @"$s8ZeroInit3FooV1yAA9TestFloatVvpZ" ={{.*}} global %T8ZeroInit9TestFloatV zeroinitializer
// CHECK: @"$s8ZeroInit3FooV1zAA10TestVectorVvpZ" ={{.*}} global %T8ZeroInit10TestVectorV zeroinitializer
// CHECK-NOT: swift_once