Skip to content

Implement basic support for Builtin.IntegerLiteral #20200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 1, 2018
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
1 change: 1 addition & 0 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ Types
type ::= 'BB' // Builtin.UnsafeValueBuffer
type ::= 'Bf' NATURAL '_' // Builtin.Float<n>
type ::= 'Bi' NATURAL '_' // Builtin.Int<n>
type ::= 'BI' // Builtin.IntLiteral
type ::= 'BO' // Builtin.UnknownObject
type ::= 'Bo' // Builtin.NativeObject
type ::= 'Bp' // Builtin.RawPointer
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ class ASTContext final {
const CanType TheRawPointerType; /// Builtin.RawPointer
const CanType TheUnsafeValueBufferType; /// Builtin.UnsafeValueBuffer
const CanType TheSILTokenType; /// Builtin.SILToken
const CanType TheIntegerLiteralType; /// Builtin.IntegerLiteralType

const CanType TheIEEE32Type; /// 32-bit IEEE floating point
const CanType TheIEEE64Type; /// 64-bit IEEE floating point
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,8 @@ ERROR(sil_operand_not_ref_storage_address,none,
(StringRef, StringRef, ReferenceOwnership))
ERROR(sil_integer_literal_not_integer_type,none,
"integer_literal instruction requires a 'Builtin.Int<n>' type", ())
ERROR(sil_integer_literal_not_well_formed,none,
"integer_literal value not well-formed for type %0", (Type))
ERROR(sil_float_literal_not_float_type,none,
"float_literal instruction requires a 'Builtin.FP<n>' type", ())
ERROR(sil_substitutions_on_non_polymorphic_type,none,
Expand Down
6 changes: 4 additions & 2 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,10 +789,12 @@ class IntegerLiteralExpr : public NumberLiteralExpr {
static IntegerLiteralExpr *
createFromUnsigned(ASTContext &C, unsigned value);

/// Returns the value of the literal, appropriately constructed in the
/// target type.
APInt getValue() const;
static APInt getValue(StringRef Text, unsigned BitWidth, bool Negative);

APInt getRawMagnitude() const;
/// Returns the raw value of the literal without any truncation.
APInt getRawValue() const;

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::IntegerLiteral;
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class TypeMatcher {

TRIVIAL_CASE(ErrorType)
TRIVIAL_CASE(BuiltinIntegerType)
TRIVIAL_CASE(BuiltinIntegerLiteralType)
TRIVIAL_CASE(BuiltinFloatType)
TRIVIAL_CASE(BuiltinRawPointerType)
TRIVIAL_CASE(BuiltinNativeObjectType)
Expand Down
5 changes: 4 additions & 1 deletion include/swift/AST/TypeNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
TYPE(Error, Type)
UNCHECKED_TYPE(Unresolved, Type)
ABSTRACT_TYPE(Builtin, Type)
BUILTIN_TYPE(BuiltinInteger, BuiltinType)
ABSTRACT_TYPE(AnyBuiltinInteger, BuiltinType)
BUILTIN_TYPE(BuiltinInteger, AnyBuiltinIntegerType)
BUILTIN_TYPE(BuiltinIntegerLiteral, AnyBuiltinIntegerType)
TYPE_RANGE(AnyBuiltinInteger, BuiltinInteger, BuiltinIntegerLiteral)
BUILTIN_TYPE(BuiltinFloat, BuiltinType)
BUILTIN_TYPE(BuiltinRawPointer, BuiltinType)
BUILTIN_TYPE(BuiltinNativeObject, BuiltinType)
Expand Down
81 changes: 71 additions & 10 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1346,13 +1346,17 @@ END_CAN_TYPE_WRAPPER(BuiltinVectorType, BuiltinType)
class BuiltinIntegerWidth {
/// Tag values for abstract integer sizes.
enum : unsigned {
Least_SpecialValue = ~2U,
/// Inhabitants stolen for use as DenseMap special values.
DenseMapEmpty = ~0U,
DenseMapTombstone = ~1U,

/// An arbitrary-precision integer.
ArbitraryWidth = ~2U,

/// The size of a pointer on the target system.
PointerWidth = ~0U,
PointerWidth = ~3U,

/// Inhabitants stolen for use as DenseMap special values.
DenseMapEmpty = ~1U,
DenseMapTombstone = ~2U,
Least_SpecialValue = ~3U,
};

unsigned RawValue;
Expand All @@ -1372,6 +1376,10 @@ class BuiltinIntegerWidth {
static BuiltinIntegerWidth pointer() {
return BuiltinIntegerWidth(PointerWidth);
}

static BuiltinIntegerWidth arbitrary() {
return BuiltinIntegerWidth(ArbitraryWidth);
}

/// Is this a fixed width?
bool isFixedWidth() const { return RawValue < Least_SpecialValue; }
Expand All @@ -1384,6 +1392,9 @@ class BuiltinIntegerWidth {

/// Is this the abstract target pointer width?
bool isPointerWidth() const { return RawValue == PointerWidth; }

/// Is this the abstract arbitrary-width value?
bool isArbitraryWidth() const { return RawValue == ArbitraryWidth; }

/// Get the least supported value for the width.
///
Expand All @@ -1393,6 +1404,8 @@ class BuiltinIntegerWidth {
return getFixedWidth();
if (isPointerWidth())
return 32;
if (isArbitraryWidth())
return 1;
llvm_unreachable("impossible width value");
}

Expand All @@ -1404,8 +1417,16 @@ class BuiltinIntegerWidth {
return getFixedWidth();
if (isPointerWidth())
return 64;
if (isArbitraryWidth())
return ~0U;
llvm_unreachable("impossible width value");
}

/// Parse a value of this bit-width.
///
/// If the radix is 0, it is autosensed.
APInt parse(StringRef text, unsigned radix, bool negate,
bool *hadError = nullptr) const;

friend bool operator==(BuiltinIntegerWidth a, BuiltinIntegerWidth b) {
return a.RawValue == b.RawValue;
Expand All @@ -1415,15 +1436,31 @@ class BuiltinIntegerWidth {
}
};

/// An abstract base class for the two integer types.
class AnyBuiltinIntegerType : public BuiltinType {
protected:
AnyBuiltinIntegerType(TypeKind kind, const ASTContext &C)
: BuiltinType(kind, C) {}

public:
static bool classof(const TypeBase *T) {
return T->getKind() >= TypeKind::First_AnyBuiltinIntegerType &&
T->getKind() <= TypeKind::Last_AnyBuiltinIntegerType;
}

BuiltinIntegerWidth getWidth() const; // defined inline below
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(AnyBuiltinIntegerType, BuiltinType)

/// The builtin integer types. These directly correspond
/// to LLVM IR integer types. They lack signedness and have an arbitrary
/// bitwidth.
class BuiltinIntegerType : public BuiltinType {
class BuiltinIntegerType : public AnyBuiltinIntegerType {
friend class ASTContext;
private:
BuiltinIntegerWidth Width;
BuiltinIntegerType(BuiltinIntegerWidth BitWidth, const ASTContext &C)
: BuiltinType(TypeKind::BuiltinInteger, C), Width(BitWidth) {}
: AnyBuiltinIntegerType(TypeKind::BuiltinInteger, C), Width(BitWidth) {}

public:
/// Get a builtin integer type.
Expand All @@ -1440,7 +1477,8 @@ class BuiltinIntegerType : public BuiltinType {
return get(BuiltinIntegerWidth::pointer(), C);
}

/// Return the bit width of the integer.
/// Return the bit width of the integer. Always returns a non-arbitrary
/// width.
BuiltinIntegerWidth getWidth() const {
return Width;
}
Expand Down Expand Up @@ -1478,8 +1516,31 @@ class BuiltinIntegerType : public BuiltinType {
return T->getKind() == TypeKind::BuiltinInteger;
}
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinIntegerType, BuiltinType)

DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinIntegerType, AnyBuiltinIntegerType)

/// BuiltinIntegerLiteralType - The builtin arbitrary-precision integer type.
/// Useful for constructing integer literals.
class BuiltinIntegerLiteralType : public AnyBuiltinIntegerType {
friend class ASTContext;
BuiltinIntegerLiteralType(const ASTContext &C)
: AnyBuiltinIntegerType(TypeKind::BuiltinIntegerLiteral, C) {}
public:
static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::BuiltinIntegerLiteral;
}

BuiltinIntegerWidth getWidth() const = delete;
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(BuiltinIntegerLiteralType, AnyBuiltinIntegerType);

inline BuiltinIntegerWidth AnyBuiltinIntegerType::getWidth() const {
if (auto intTy = dyn_cast<BuiltinIntegerType>(this)) {
return intTy->getWidth();
} else {
return BuiltinIntegerWidth::arbitrary();
}
}

class BuiltinFloatType : public BuiltinType {
friend class ASTContext;
public:
Expand Down
54 changes: 54 additions & 0 deletions include/swift/Basic/APIntMap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===--- APIntMap.h - A map with APInts as the keys -------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// LLVM does not allow arbitrary APInts to be the keys of a DenseMap because
// APInts are only comparable if they have the same bit-width. This map
// implementation assumes that its keys will always be constrained to their
// minimum width, so it's not a general-purpose structure, but it does work.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_BASIC_APINTMAP_H
#define SWIFT_BASIC_APINTMAP_H

#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "swift/Basic/LLVM.h"

namespace swift {

struct WidthPreservingAPIntDenseMapInfo {
// For the special values, we use -1 with a bit-width that isn't minimal
// for the value, then use a parser that always produces values with
// minimal bit-widths so that we don't get a conflict.
static inline APInt getEmptyKey() {
return APInt::getAllOnesValue(/*bitwidth*/2);
}
static inline APInt getTombstoneKey() {
return APInt::getAllOnesValue(/*bitwidth*/3);
}

static unsigned getHashValue(const APInt &Key) {
return static_cast<unsigned>(hash_value(Key));
}

static bool isEqual(const APInt &LHS, const APInt &RHS) {
return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS;
}
};

template <class Value>
using APIntMap = llvm::DenseMap<APInt, Value, WidthPreservingAPIntDenseMapInfo>;

}

#endif
2 changes: 2 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,8 @@ class Parser {
ParserResult<Expr> parseExprStringLiteral();
ParserResult<Expr> parseExprTypeOf();

StringRef copyAndStripUnderscores(StringRef text);

ParserStatus parseStringSegments(SmallVectorImpl<Lexer::StringSegment> &Segments,
SmallVectorImpl<Expr*> &Exprs,
Token EntireTok);
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SIL/SILType.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,8 @@ class SILType {
static SILType getRawPointerType(const ASTContext &C);
/// Get a builtin integer type as a SILType.
static SILType getBuiltinIntegerType(unsigned bitWidth, const ASTContext &C);
/// Get the IntegerLiteral type as a SILType.
static SILType getBuiltinIntegerLiteralType(const ASTContext &C);
/// Get a builtin floating-point type as a SILType.
static SILType getBuiltinFloatType(BuiltinFloatType::FPKind Kind,
const ASTContext &C);
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ constexpr static const char BUILTIN_TYPE_NAME_INT128[] = "Builtin.Int128";
constexpr static const char BUILTIN_TYPE_NAME_INT256[] = "Builtin.Int256";
/// The name of the Builtin type for Int512
constexpr static const char BUILTIN_TYPE_NAME_INT512[] = "Builtin.Int512";
/// The name of the Builtin type for IntLiteral
constexpr static const char BUILTIN_TYPE_NAME_INTLITERAL[] =
"Builtin.IntLiteral";
/// The name of the Builtin type for Float
constexpr static const char BUILTIN_TYPE_NAME_FLOAT[] = "Builtin.Float";
/// The name of the Builtin type for NativeObject
Expand Down
3 changes: 3 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ ASTContext::ASTContext(LangOptions &langOpts, SearchPathOptions &SearchPathOpts,
BuiltinUnsafeValueBufferType(*this)),
TheSILTokenType(new (*this, AllocationArena::Permanent)
SILTokenType(*this)),
TheIntegerLiteralType(new (*this, AllocationArena::Permanent)
BuiltinIntegerLiteralType(*this)),
TheIEEE32Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE32,*this)),
TheIEEE64Type(new (*this, AllocationArena::Permanent)
Expand Down Expand Up @@ -3032,6 +3034,7 @@ Type ErrorType::get(Type originalType) {

BuiltinIntegerType *BuiltinIntegerType::get(BuiltinIntegerWidth BitWidth,
const ASTContext &C) {
assert(!BitWidth.isArbitraryWidth());
BuiltinIntegerType *&Result = C.getImpl().IntegerTypes[BitWidth];
if (Result == nullptr)
Result = new (C, AllocationArena::Permanent) BuiltinIntegerType(BitWidth,C);
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,7 @@ namespace {
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

TRIVIAL_TYPE_PRINTER(BuiltinIntegerLiteral, builtin_integer_literal)
TRIVIAL_TYPE_PRINTER(BuiltinRawPointer, builtin_raw_pointer)
TRIVIAL_TYPE_PRINTER(BuiltinNativeObject, builtin_native_object)
TRIVIAL_TYPE_PRINTER(BuiltinBridgeObject, builtin_bridge_object)
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,8 @@ void ASTMangler::appendType(Type type) {
llvm_unreachable("impossible width value");
return;
}
case TypeKind::BuiltinIntegerLiteral:
return appendOperator("BI");
case TypeKind::BuiltinRawPointer:
return appendOperator("Bp");
case TypeKind::BuiltinNativeObject:
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3369,6 +3369,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
Printer << BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER;
}

void visitBuiltinIntegerLiteralType(BuiltinIntegerLiteralType *T) {
Printer << BUILTIN_TYPE_NAME_INTLITERAL;
}

void visitBuiltinVectorType(BuiltinVectorType *T) {
llvm::SmallString<32> UnderlyingStrVec;
StringRef UnderlyingStr;
Expand Down
5 changes: 2 additions & 3 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,9 +2039,8 @@ class Verifier : public ASTWalker {
void verifyChecked(IfExpr *E) {
PrettyStackTraceExpr debugStack(Ctx, "verifying IfExpr", E);

auto condTy
= E->getCondExpr()->getType()->getAs<BuiltinIntegerType>();
if (!condTy || !condTy->isFixedWidth() || condTy->getFixedWidth() != 1) {
auto condTy = E->getCondExpr()->getType();
if (!condTy->isBuiltinIntegerType(1)) {
Out << "IfExpr condition is not an i1\n";
abort();
}
Expand Down
Loading