[torque] Add unsafe cast to Torque.
This CL is a proposal to add "checked" casts (CAST in CSA) to the Torque language. The CL adds the "unsafe_cast<>" operator that emits a "CAST". Example: let n: Number = ...; ... if (TaggedIsSmi(n)) { let m: Smi = unsafe_cast<Smi>(n); ... } The cast wont incur a runtime overhead now. R=tebbi@chromium.org Change-Id: I9fca90d1d11e61617ba0270e5022fd66200e2195 Reviewed-on: https://chromium-review.googlesource.com/1070151 Commit-Queue: Simon Zünd <szuend@google.com> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#53416}
This commit is contained in:
parent
0fd549f885
commit
9ef4df2f30
@ -18,6 +18,7 @@ IMPLICIT: 'implicit';
|
||||
DEFERRED: 'deferred';
|
||||
IF: 'if';
|
||||
CAST_KEYWORD: 'cast';
|
||||
UNSAFE_CAST_KEYWORD: 'unsafe_cast';
|
||||
CONVERT_KEYWORD: 'convert';
|
||||
FOR: 'for';
|
||||
WHILE: 'while';
|
||||
@ -216,6 +217,7 @@ primaryExpression
|
||||
| DECIMAL_LITERAL
|
||||
| STRING_LITERAL
|
||||
| CAST_KEYWORD '<' type '>' '(' expression ')' OTHERWISE IDENTIFIER
|
||||
| UNSAFE_CAST_KEYWORD '<' type '>' '(' expression ')'
|
||||
| CONVERT_KEYWORD '<' type '>' '(' expression ')'
|
||||
| ('(' expression ')');
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,60 +43,61 @@ class TorqueLexer : public antlr4::Lexer {
|
||||
DEFERRED = 28,
|
||||
IF = 29,
|
||||
CAST_KEYWORD = 30,
|
||||
CONVERT_KEYWORD = 31,
|
||||
FOR = 32,
|
||||
WHILE = 33,
|
||||
RETURN = 34,
|
||||
CONSTEXPR = 35,
|
||||
CONTINUE = 36,
|
||||
BREAK = 37,
|
||||
GOTO = 38,
|
||||
OTHERWISE = 39,
|
||||
TRY = 40,
|
||||
CATCH = 41,
|
||||
LABEL = 42,
|
||||
LABELS = 43,
|
||||
TAIL = 44,
|
||||
ISNT = 45,
|
||||
IS = 46,
|
||||
LET = 47,
|
||||
EXTERN = 48,
|
||||
ASSERT_TOKEN = 49,
|
||||
CHECK_TOKEN = 50,
|
||||
UNREACHABLE_TOKEN = 51,
|
||||
DEBUG_TOKEN = 52,
|
||||
ASSIGNMENT = 53,
|
||||
ASSIGNMENT_OPERATOR = 54,
|
||||
EQUAL = 55,
|
||||
PLUS = 56,
|
||||
MINUS = 57,
|
||||
MULTIPLY = 58,
|
||||
DIVIDE = 59,
|
||||
MODULO = 60,
|
||||
BIT_OR = 61,
|
||||
BIT_AND = 62,
|
||||
BIT_NOT = 63,
|
||||
MAX = 64,
|
||||
MIN = 65,
|
||||
NOT_EQUAL = 66,
|
||||
LESS_THAN = 67,
|
||||
LESS_THAN_EQUAL = 68,
|
||||
GREATER_THAN = 69,
|
||||
GREATER_THAN_EQUAL = 70,
|
||||
SHIFT_LEFT = 71,
|
||||
SHIFT_RIGHT = 72,
|
||||
SHIFT_RIGHT_ARITHMETIC = 73,
|
||||
VARARGS = 74,
|
||||
EQUALITY_OPERATOR = 75,
|
||||
INCREMENT = 76,
|
||||
DECREMENT = 77,
|
||||
NOT = 78,
|
||||
STRING_LITERAL = 79,
|
||||
IDENTIFIER = 80,
|
||||
WS = 81,
|
||||
BLOCK_COMMENT = 82,
|
||||
LINE_COMMENT = 83,
|
||||
DECIMAL_LITERAL = 84
|
||||
UNSAFE_CAST_KEYWORD = 31,
|
||||
CONVERT_KEYWORD = 32,
|
||||
FOR = 33,
|
||||
WHILE = 34,
|
||||
RETURN = 35,
|
||||
CONSTEXPR = 36,
|
||||
CONTINUE = 37,
|
||||
BREAK = 38,
|
||||
GOTO = 39,
|
||||
OTHERWISE = 40,
|
||||
TRY = 41,
|
||||
CATCH = 42,
|
||||
LABEL = 43,
|
||||
LABELS = 44,
|
||||
TAIL = 45,
|
||||
ISNT = 46,
|
||||
IS = 47,
|
||||
LET = 48,
|
||||
EXTERN = 49,
|
||||
ASSERT_TOKEN = 50,
|
||||
CHECK_TOKEN = 51,
|
||||
UNREACHABLE_TOKEN = 52,
|
||||
DEBUG_TOKEN = 53,
|
||||
ASSIGNMENT = 54,
|
||||
ASSIGNMENT_OPERATOR = 55,
|
||||
EQUAL = 56,
|
||||
PLUS = 57,
|
||||
MINUS = 58,
|
||||
MULTIPLY = 59,
|
||||
DIVIDE = 60,
|
||||
MODULO = 61,
|
||||
BIT_OR = 62,
|
||||
BIT_AND = 63,
|
||||
BIT_NOT = 64,
|
||||
MAX = 65,
|
||||
MIN = 66,
|
||||
NOT_EQUAL = 67,
|
||||
LESS_THAN = 68,
|
||||
LESS_THAN_EQUAL = 69,
|
||||
GREATER_THAN = 70,
|
||||
GREATER_THAN_EQUAL = 71,
|
||||
SHIFT_LEFT = 72,
|
||||
SHIFT_RIGHT = 73,
|
||||
SHIFT_RIGHT_ARITHMETIC = 74,
|
||||
VARARGS = 75,
|
||||
EQUALITY_OPERATOR = 76,
|
||||
INCREMENT = 77,
|
||||
DECREMENT = 78,
|
||||
NOT = 79,
|
||||
STRING_LITERAL = 80,
|
||||
IDENTIFIER = 81,
|
||||
WS = 82,
|
||||
BLOCK_COMMENT = 83,
|
||||
LINE_COMMENT = 84,
|
||||
DECIMAL_LITERAL = 85
|
||||
};
|
||||
|
||||
explicit TorqueLexer(antlr4::CharStream* input);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,60 +43,61 @@ class TorqueParser : public antlr4::Parser {
|
||||
DEFERRED = 28,
|
||||
IF = 29,
|
||||
CAST_KEYWORD = 30,
|
||||
CONVERT_KEYWORD = 31,
|
||||
FOR = 32,
|
||||
WHILE = 33,
|
||||
RETURN = 34,
|
||||
CONSTEXPR = 35,
|
||||
CONTINUE = 36,
|
||||
BREAK = 37,
|
||||
GOTO = 38,
|
||||
OTHERWISE = 39,
|
||||
TRY = 40,
|
||||
CATCH = 41,
|
||||
LABEL = 42,
|
||||
LABELS = 43,
|
||||
TAIL = 44,
|
||||
ISNT = 45,
|
||||
IS = 46,
|
||||
LET = 47,
|
||||
EXTERN = 48,
|
||||
ASSERT_TOKEN = 49,
|
||||
CHECK_TOKEN = 50,
|
||||
UNREACHABLE_TOKEN = 51,
|
||||
DEBUG_TOKEN = 52,
|
||||
ASSIGNMENT = 53,
|
||||
ASSIGNMENT_OPERATOR = 54,
|
||||
EQUAL = 55,
|
||||
PLUS = 56,
|
||||
MINUS = 57,
|
||||
MULTIPLY = 58,
|
||||
DIVIDE = 59,
|
||||
MODULO = 60,
|
||||
BIT_OR = 61,
|
||||
BIT_AND = 62,
|
||||
BIT_NOT = 63,
|
||||
MAX = 64,
|
||||
MIN = 65,
|
||||
NOT_EQUAL = 66,
|
||||
LESS_THAN = 67,
|
||||
LESS_THAN_EQUAL = 68,
|
||||
GREATER_THAN = 69,
|
||||
GREATER_THAN_EQUAL = 70,
|
||||
SHIFT_LEFT = 71,
|
||||
SHIFT_RIGHT = 72,
|
||||
SHIFT_RIGHT_ARITHMETIC = 73,
|
||||
VARARGS = 74,
|
||||
EQUALITY_OPERATOR = 75,
|
||||
INCREMENT = 76,
|
||||
DECREMENT = 77,
|
||||
NOT = 78,
|
||||
STRING_LITERAL = 79,
|
||||
IDENTIFIER = 80,
|
||||
WS = 81,
|
||||
BLOCK_COMMENT = 82,
|
||||
LINE_COMMENT = 83,
|
||||
DECIMAL_LITERAL = 84
|
||||
UNSAFE_CAST_KEYWORD = 31,
|
||||
CONVERT_KEYWORD = 32,
|
||||
FOR = 33,
|
||||
WHILE = 34,
|
||||
RETURN = 35,
|
||||
CONSTEXPR = 36,
|
||||
CONTINUE = 37,
|
||||
BREAK = 38,
|
||||
GOTO = 39,
|
||||
OTHERWISE = 40,
|
||||
TRY = 41,
|
||||
CATCH = 42,
|
||||
LABEL = 43,
|
||||
LABELS = 44,
|
||||
TAIL = 45,
|
||||
ISNT = 46,
|
||||
IS = 47,
|
||||
LET = 48,
|
||||
EXTERN = 49,
|
||||
ASSERT_TOKEN = 50,
|
||||
CHECK_TOKEN = 51,
|
||||
UNREACHABLE_TOKEN = 52,
|
||||
DEBUG_TOKEN = 53,
|
||||
ASSIGNMENT = 54,
|
||||
ASSIGNMENT_OPERATOR = 55,
|
||||
EQUAL = 56,
|
||||
PLUS = 57,
|
||||
MINUS = 58,
|
||||
MULTIPLY = 59,
|
||||
DIVIDE = 60,
|
||||
MODULO = 61,
|
||||
BIT_OR = 62,
|
||||
BIT_AND = 63,
|
||||
BIT_NOT = 64,
|
||||
MAX = 65,
|
||||
MIN = 66,
|
||||
NOT_EQUAL = 67,
|
||||
LESS_THAN = 68,
|
||||
LESS_THAN_EQUAL = 69,
|
||||
GREATER_THAN = 70,
|
||||
GREATER_THAN_EQUAL = 71,
|
||||
SHIFT_LEFT = 72,
|
||||
SHIFT_RIGHT = 73,
|
||||
SHIFT_RIGHT_ARITHMETIC = 74,
|
||||
VARARGS = 75,
|
||||
EQUALITY_OPERATOR = 76,
|
||||
INCREMENT = 77,
|
||||
DECREMENT = 78,
|
||||
NOT = 79,
|
||||
STRING_LITERAL = 80,
|
||||
IDENTIFIER = 81,
|
||||
WS = 82,
|
||||
BLOCK_COMMENT = 83,
|
||||
LINE_COMMENT = 84,
|
||||
DECIMAL_LITERAL = 85
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -737,6 +738,7 @@ class TorqueParser : public antlr4::Parser {
|
||||
ExpressionContext* expression();
|
||||
antlr4::tree::TerminalNode* OTHERWISE();
|
||||
antlr4::tree::TerminalNode* IDENTIFIER();
|
||||
antlr4::tree::TerminalNode* UNSAFE_CAST_KEYWORD();
|
||||
antlr4::tree::TerminalNode* CONVERT_KEYWORD();
|
||||
|
||||
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
|
||||
|
@ -553,6 +553,10 @@ antlrcpp::Any AstGenerator::visitPrimaryExpression(
|
||||
return implicit_cast<Expression*>(RegisterNode(new ConvertExpression{
|
||||
Pos(context), GetType(context->type()),
|
||||
context->expression()->accept(this).as<Expression*>()}));
|
||||
if (context->UNSAFE_CAST_KEYWORD())
|
||||
return implicit_cast<Expression*>(RegisterNode(new UnsafeCastExpression{
|
||||
Pos(context), GetType(context->type()),
|
||||
context->expression()->accept(this).as<Expression*>()}));
|
||||
if (context->CAST_KEYWORD())
|
||||
return implicit_cast<Expression*>(RegisterNode(new CastExpression{
|
||||
Pos(context), GetType(context->type()),
|
||||
|
@ -40,6 +40,7 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
|
||||
V(AssignmentExpression) \
|
||||
V(IncrementDecrementExpression) \
|
||||
V(CastExpression) \
|
||||
V(UnsafeCastExpression) \
|
||||
V(ConvertExpression)
|
||||
|
||||
#define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \
|
||||
@ -320,6 +321,14 @@ struct ConvertExpression : Expression {
|
||||
Expression* value;
|
||||
};
|
||||
|
||||
struct UnsafeCastExpression : Expression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(UnsafeCastExpression)
|
||||
UnsafeCastExpression(SourcePosition p, TypeExpression* t, Expression* v)
|
||||
: Expression(kKind, p), type(t), value(v) {}
|
||||
TypeExpression* type;
|
||||
Expression* value;
|
||||
};
|
||||
|
||||
struct ElementAccessExpression : LocationExpression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(ElementAccessExpression)
|
||||
ElementAccessExpression(SourcePosition p, Expression* a, Expression* i)
|
||||
|
@ -60,6 +60,7 @@ class DeclarationVisitor : public FileVisitor {
|
||||
}
|
||||
void Visit(FieldAccessExpression* expr) { Visit(expr->object); }
|
||||
void Visit(CastExpression* expr) { Visit(expr->value); }
|
||||
void Visit(UnsafeCastExpression* expr) { Visit(expr->value); }
|
||||
void Visit(ConvertExpression* expr) { Visit(expr->value); }
|
||||
void Visit(BlockStatement* expr) {
|
||||
Declarations::NodeScopeActivator scope(declarations(), expr);
|
||||
|
@ -526,6 +526,21 @@ VisitResult ImplementationVisitor::Visit(CastExpression* expr) {
|
||||
return GenerateOperation("cast<>", args, declarations()->GetType(expr->type));
|
||||
}
|
||||
|
||||
VisitResult ImplementationVisitor::Visit(UnsafeCastExpression* expr) {
|
||||
const Type* type = declarations()->GetType(expr->type);
|
||||
if (type->IsConstexpr()) {
|
||||
ReportError("unsafe_cast can only be used for non constexpr types.");
|
||||
}
|
||||
|
||||
VisitResult result = Visit(expr->value);
|
||||
|
||||
std::string result_variable_name = GenerateNewTempVariable(type);
|
||||
source_out() << "CAST(";
|
||||
source_out() << result.variable();
|
||||
source_out() << ");\n";
|
||||
return VisitResult{type, result_variable_name};
|
||||
}
|
||||
|
||||
VisitResult ImplementationVisitor::Visit(ConvertExpression* expr) {
|
||||
Arguments args;
|
||||
args.parameters = {Visit(expr->value)};
|
||||
|
@ -84,6 +84,7 @@ class ImplementationVisitor : public FileVisitor {
|
||||
}
|
||||
|
||||
VisitResult Visit(CastExpression* expr);
|
||||
VisitResult Visit(UnsafeCastExpression* expr);
|
||||
VisitResult Visit(ConvertExpression* expr);
|
||||
|
||||
void Visit(ModuleDeclaration* decl);
|
||||
|
@ -156,6 +156,20 @@ TEST(TestFunctionPointerToGeneric) {
|
||||
ft.Call();
|
||||
}
|
||||
|
||||
TEST(TestUnsafeCast) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
CodeAssemblerTester asm_tester(isolate, 0);
|
||||
TestBuiltinsFromDSLAssembler m(asm_tester.state());
|
||||
{
|
||||
Node* temp = m.SmiConstant(0);
|
||||
Node* n = m.SmiConstant(10);
|
||||
m.Return(m.TestUnsafeCast(m.UncheckedCast<Context>(temp),
|
||||
m.UncheckedCast<Number>(n)));
|
||||
}
|
||||
FunctionTester ft(asm_tester.GenerateCode(), 0);
|
||||
ft.CheckCall(ft.true_value());
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -193,4 +193,14 @@ module test {
|
||||
macro TestTypeAlias(x : SmiToSmi) : Code {
|
||||
return x;
|
||||
}
|
||||
|
||||
macro TestUnsafeCast(c: Context, n: Number): Boolean {
|
||||
if (TaggedIsSmi(n)) {
|
||||
let m: Smi = unsafe_cast<Smi>(n);
|
||||
|
||||
check(TestHelperPlus1(c, m) == 11);
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user