Files
swift-mirror/lib/Parse/ParseSIL.cpp
Chris Lattner 8c85a49d2a with the groundwork out of the way, we can now namebind types referenced
by the SIL parser.  Add a test that covers both local types, and types
that require looking through an import decl (Int, from the stdlib).


Swift SVN r5249
2013-05-21 05:34:24 +00:00

178 lines
5.4 KiB
C++

//===--- ParseSIL.cpp - SIL File Parsing logic ----------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "Parser.h"
#include "swift/Parse/Lexer.h"
#include "swift/SIL/SILModule.h"
#include "swift/Subsystems.h"
#include "llvm/Support/SaveAndRestore.h"
using namespace swift;
/// parseSILLinkage - Parse a linkage specifier if present.
/// sil-linkage:
/// /*empty*/ // defaults to external linkage.
/// 'internal'
/// 'clang_thunk'
static bool parseSILLinkage(SILLinkage &Result, Parser &P) {
if (P.Tok.isNot(tok::identifier)) {
Result = SILLinkage::External;
} else if (P.Tok.getText() == "internal") {
Result = SILLinkage::Internal;
P.consumeToken(tok::identifier);
} else if (P.Tok.getText() == "clang_thunk") {
Result = SILLinkage::ClangThunk;
P.consumeToken(tok::identifier);
} else {
P.diagnose(P.Tok, diag::expected_sil_linkage_or_function);
return true;
}
return false;
}
/// decl-sil: [[only in SIL mode]]
/// 'sil' sil-linkage '@' identifier ':' sil-type decl-sil-body
/// decl-sil-body:
/// '{' sil-basic-block+ '}'
bool Parser::parseDeclSIL() {
// Inform the lexer that we're lexing the body of the SIL declaration. Do
// this before we consume the 'sil' token so that all later tokens are
// properly handled.
Lexer::SILBodyRAII Tmp(*L);
consumeToken(tok::kw_sil);
SILLinkage FnLinkage;
Identifier FnName;
SILType FnType;
if (parseSILLinkage(FnLinkage, *this) ||
parseToken(tok::sil_at_sign, diag::expected_sil_function_name) ||
parseIdentifier(FnName, diag::expected_sil_function_name) ||
parseToken(tok::colon, diag::expected_sil_type) ||
parseSILType(FnType))
return true;
SILFunction *Fn = new (*SIL) SILFunction(*SIL, FnLinkage,
FnName.str(), FnType);
(void)Fn;
// Now that we have a SILFunction parse the body, if present.
SourceLoc LBraceLoc = Tok.getLoc();
if (consumeIf(tok::l_brace)) {
// TODO: parse the body.
SourceLoc RBraceLoc;
parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
LBraceLoc);
}
// TODO: Verify it is a function type.
return false;
}
/// sil-type:
/// '$' sil-type-attributes? '*'? type
/// sil-type-attributes:
/// '[' sil-type-attribute (',' sil-type-attribute)* ']'
/// sil-type-attribute:
/// 'sil_sret'
/// 'sil_uncurry' '=' integer_literal
///
bool Parser::parseSILType(SILType &Result) {
bool IsSRet = false;
unsigned UncurryLevel = 0;
// If we have sil-type-attribute list, parse it.
if (Tok.is(tok::l_square) && peekToken().is(tok::identifier) &&
peekToken().getText().startswith("sil_")) {
SourceLoc LeftLoc = Tok.getLoc(), RightLoc;
// The attribute list is always guaranteed to have at least one attribute.
do {
consumeToken();
SourceLoc AttrTokenLoc = Tok.getLoc();
Identifier AttrToken;
if (parseIdentifier(AttrToken,
diag::expected_identifier_sil_type_attributes))
return true;
if (AttrToken.str() == "sil_sret") {
IsSRet = true;
consumeToken(tok::identifier);
} else if (AttrToken.str() == "sil_uncurry") {
if (parseToken(tok::identifier, diag::malformed_sil_uncurry_attribute)||
parseToken(tok::equal, diag::malformed_sil_uncurry_attribute))
return true;
if (Tok.isNot(tok::integer_literal) ||
Tok.getText().getAsInteger(10, UncurryLevel)) {
diagnose(Tok, diag::malformed_sil_uncurry_attribute);
return true;
}
consumeToken(tok::integer_literal);
} else {
diagnose(AttrTokenLoc, diag::unknown_sil_type_attribute);
return true;
}
// Continue parsing the next token.
} while (Tok.is(tok::comma));
if (parseMatchingToken(tok::r_square, RightLoc,
diag::expected_bracket_sil_type_attributes, LeftLoc))
return true;
}
// If we have a '*', then this is an address type.
bool isAddress = false;
if (Tok.isAnyOperator() && Tok.getText() == "*") {
isAddress = true;
consumeToken();
}
TypeLoc Ty;
if (parseToken(tok::sil_dollar, diag::expected_sil_type) ||
parseType(Ty, diag::expected_sil_type))
return true;
// If we successfully parsed the type, do some type checking / name binding
// of it.
{
// We have to lie and say we're done with parsing to make this happen.
assert(TU->ASTStage == TranslationUnit::Parsing &&
"Unexpected stage during parsing!");
llvm::SaveAndRestore<Module::ASTStage_t> ASTStage(TU->ASTStage,
TranslationUnit::Parsed);
if (performTypeLocChecking(TU, Ty))
return true;
}
// FIXME: Stop using TypeConverter when SILType for functions doesn't contain
// SILTypes itself.
(void)IsSRet;
Result = SIL->Types.getLoweredType(Ty.getType(), UncurryLevel);
// performNameBinding(TU);
// performTypeChecking(TU);
return false;
}