Files
swift-mirror/lib/AST/Builtins.cpp
John McCall b2a2027a43 Revert r1144, r1145, and r1146. These changes (which removed ParenType
in favor of a single-element non-canonical TupleType) broke the type
system, in that supposed sugar (the TupleType) supported a different
set of operations from the canonical type.  For example, a
single-element unlabelled tuple type supports elementwise projection
(foo.$0), but the underlying element does not (or supports it
differently).

The IR-gen failure was due to a very related problem:  IR-gen
was not updated to reflect that a single unlabelled tuple element
is the same type as its element type, and therefore it was giving
different representations to these types ({ %foo } and %foo,
respectively), which broke widespread assumptions.

The removal of ParenType was done in pursuit of an AST invariant
that's not actually particularly interesting in the first place
and which, furthermore, is problematic to attain.

Swift SVN r1182
2012-03-11 09:15:21 +00:00

167 lines
5.8 KiB
C++

//===--- Builtins.cpp - Swift Language Builtin ASTs -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the interface to the Builtin APIs.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/Builtins.h"
#include "swift/AST/AST.h"
#include "llvm/ADT/StringSwitch.h"
using namespace swift;
Type swift::getBuiltinType(ASTContext &Context, StringRef Name) {
if (Name == "FPIEEE32")
return Context.TheIEEE32Type;
if (Name == "FPIEEE64")
return Context.TheIEEE64Type;
// Handle 'int8' and friends.
if (Name.substr(0, 3) == "Int") {
unsigned BitWidth;
if (!Name.substr(3).getAsInteger(10, BitWidth) &&
BitWidth <= 1024 && BitWidth != 0) // Cap to prevent insane things.
return BuiltinIntegerType::get(BitWidth, Context);
}
// Target specific FP types.
if (Name == "FPIEEE16")
return Context.TheIEEE16Type;
if (Name == "FPIEEE80")
return Context.TheIEEE80Type;
if (Name == "FPIEEE128")
return Context.TheIEEE128Type;
if (Name == "FPPPC128")
return Context.ThePPC128Type;
return Type();
}
BuiltinValueKind swift::isBuiltinValue(ASTContext &C, StringRef Name, Type &Ty){
// builtin-id ::= operation-id '_' type-id
// This will almost certainly get more sophisticated.
StringRef::size_type Underscore = Name.find_last_of('_');
if (Underscore == StringRef::npos) return BuiltinValueKind::None;
// Check that the type parameter is well-formed and set it up for returning.
Ty = getBuiltinType(C, Name.substr(Underscore + 1));
if (Ty.isNull())
return BuiltinValueKind::None;
// Check that the operation name is well-formed.
StringRef OperationName = Name.substr(0, Underscore);
return llvm::StringSwitch<BuiltinValueKind>(OperationName)
#define BUILTIN(id, name) \
.Case(name, BuiltinValueKind::id)
#include "swift/AST/Builtins.def"
.Default(BuiltinValueKind::None);
}
/// Build a builtin function declarations.
static FuncDecl *getBuiltinFunction(ASTContext &Context, Identifier Id, Type T){
return new (Context) FuncDecl(SourceLoc(), SourceLoc(), Id, T,
/*init*/ nullptr, Context.TheBuiltinModule);
}
/// Build a unary operation declaration.
static ValueDecl *getUnaryOperation(ASTContext &Context, Identifier Id,
Type ArgType) {
Type FnTy = FunctionType::get(ArgType, ArgType, Context);
return getBuiltinFunction(Context, Id, FnTy);
}
/// Build a binary operation declaration.
static ValueDecl *getBinaryOperation(ASTContext &Context, Identifier Id,
Type ArgType) {
TupleTypeElt ArgElts[] = {
TupleTypeElt(ArgType, Identifier()),
TupleTypeElt(ArgType, Identifier())
};
Type Arg = TupleType::get(ArgElts, Context);
Type FnTy = FunctionType::get(Arg, ArgType, Context);
return getBuiltinFunction(Context, Id, FnTy);
}
/// Build a binary predicate declaration.
static ValueDecl *getBinaryPredicate(ASTContext &Context, Identifier Id,
Type ArgType) {
TupleTypeElt ArgElts[] = {
TupleTypeElt(ArgType, Identifier()),
TupleTypeElt(ArgType, Identifier())
};
Type Arg = TupleType::get(ArgElts, Context);
Type FnTy = FunctionType::get(Arg, BuiltinIntegerType::get(1, Context),
Context);
return getBuiltinFunction(Context, Id, FnTy);
}
/// An array of the overloaded builtin kinds.
static const OverloadedBuiltinKind OverloadedBuiltinKinds[] = {
OverloadedBuiltinKind::None,
// There's deliberately no BUILTIN clause here so that we'll blow up
// if new builtin categories are added there and not here.
#define BUILTIN_UNARY_OPERATION(id, name, overload) overload,
#define BUILTIN_BINARY_OPERATION(id, name, overload) overload,
#define BUILTIN_BINARY_PREDICATE(id, name, overload) overload,
#include "swift/AST/Builtins.def"
};
/// Determines if a builtin type falls within the given category.
/// The category cannot be OverloadedBuiltinKind::None.
inline bool isBuiltinTypeOverloaded(Type T, OverloadedBuiltinKind OK) {
switch (OK) {
case OverloadedBuiltinKind::None:
break; // invalid
case OverloadedBuiltinKind::Integer:
return T->is<BuiltinIntegerType>();
case OverloadedBuiltinKind::Float:
return T->is<BuiltinFloatType>();
case OverloadedBuiltinKind::Arithmetic:
return true;
}
llvm_unreachable("bad overloaded builtin kind");
}
ValueDecl *swift::getBuiltinValue(ASTContext &Context, Identifier Id) {
Type ArgType;
BuiltinValueKind BV = isBuiltinValue(Context, Id.str(), ArgType);
// Filter out inappropriate overloads.
OverloadedBuiltinKind OBK = OverloadedBuiltinKinds[unsigned(BV)];
if (OBK != OverloadedBuiltinKind::None &&
!isBuiltinTypeOverloaded(ArgType, OBK))
return nullptr;
switch (BV) {
case BuiltinValueKind::None: return nullptr;
#define BUILTIN(id, name)
#define BUILTIN_UNARY_OPERATION(id, name, overload) case BuiltinValueKind::id:
#include "swift/AST/Builtins.def"
return getUnaryOperation(Context, Id, ArgType);
#define BUILTIN(id, name)
#define BUILTIN_BINARY_OPERATION(id, name, overload) case BuiltinValueKind::id:
#include "swift/AST/Builtins.def"
return getBinaryOperation(Context, Id, ArgType);
#define BUILTIN(id, name)
#define BUILTIN_BINARY_PREDICATE(id, name, overload) case BuiltinValueKind::id:
#include "swift/AST/Builtins.def"
return getBinaryPredicate(Context, Id, ArgType);
}
llvm_unreachable("bad builtin value!");
}