Commit 610c964a authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] add support for release-build checks

Change-Id: Ie8bdbcdea8006d3105c419113f9adb2c1d6f162c
Reviewed-on: https://chromium-review.googlesource.com/1070203
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53341}
parent 8ac37bc3
......@@ -36,7 +36,8 @@ ISNT: 'isnt';
IS: 'is';
LET: 'let';
EXTERN: 'extern';
ASSERT: 'assert';
ASSERT_TOKEN: 'assert';
CHECK_TOKEN: 'check';
UNREACHABLE_TOKEN: 'unreachable';
DEBUG_TOKEN: 'debug';
......@@ -241,7 +242,7 @@ gotoStatement: GOTO labelReference argumentList?;
handlerWithStatement: (CATCH IDENTIFIER | LABEL labelDeclaration) statementBlock;
tryCatch: TRY statementBlock handlerWithStatement+;
diagnosticStatement: (ASSERT '(' expression ')') | UNREACHABLE_TOKEN | DEBUG_TOKEN;
diagnosticStatement: ((ASSERT_TOKEN | CHECK_TOKEN) '(' expression ')') | UNREACHABLE_TOKEN | DEBUG_TOKEN;
statement : variableDeclarationWithInitialization ';'
| helperCallStatement ';'
......
This diff is collapsed.
......@@ -61,41 +61,42 @@ class TorqueLexer : public antlr4::Lexer {
IS = 46,
LET = 47,
EXTERN = 48,
ASSERT = 49,
UNREACHABLE_TOKEN = 50,
DEBUG_TOKEN = 51,
ASSIGNMENT = 52,
ASSIGNMENT_OPERATOR = 53,
EQUAL = 54,
PLUS = 55,
MINUS = 56,
MULTIPLY = 57,
DIVIDE = 58,
MODULO = 59,
BIT_OR = 60,
BIT_AND = 61,
BIT_NOT = 62,
MAX = 63,
MIN = 64,
NOT_EQUAL = 65,
LESS_THAN = 66,
LESS_THAN_EQUAL = 67,
GREATER_THAN = 68,
GREATER_THAN_EQUAL = 69,
SHIFT_LEFT = 70,
SHIFT_RIGHT = 71,
SHIFT_RIGHT_ARITHMETIC = 72,
VARARGS = 73,
EQUALITY_OPERATOR = 74,
INCREMENT = 75,
DECREMENT = 76,
NOT = 77,
STRING_LITERAL = 78,
IDENTIFIER = 79,
WS = 80,
BLOCK_COMMENT = 81,
LINE_COMMENT = 82,
DECIMAL_LITERAL = 83
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
};
explicit TorqueLexer(antlr4::CharStream* input);
......
This diff is collapsed.
......@@ -61,41 +61,42 @@ class TorqueParser : public antlr4::Parser {
IS = 46,
LET = 47,
EXTERN = 48,
ASSERT = 49,
UNREACHABLE_TOKEN = 50,
DEBUG_TOKEN = 51,
ASSIGNMENT = 52,
ASSIGNMENT_OPERATOR = 53,
EQUAL = 54,
PLUS = 55,
MINUS = 56,
MULTIPLY = 57,
DIVIDE = 58,
MODULO = 59,
BIT_OR = 60,
BIT_AND = 61,
BIT_NOT = 62,
MAX = 63,
MIN = 64,
NOT_EQUAL = 65,
LESS_THAN = 66,
LESS_THAN_EQUAL = 67,
GREATER_THAN = 68,
GREATER_THAN_EQUAL = 69,
SHIFT_LEFT = 70,
SHIFT_RIGHT = 71,
SHIFT_RIGHT_ARITHMETIC = 72,
VARARGS = 73,
EQUALITY_OPERATOR = 74,
INCREMENT = 75,
DECREMENT = 76,
NOT = 77,
STRING_LITERAL = 78,
IDENTIFIER = 79,
WS = 80,
BLOCK_COMMENT = 81,
LINE_COMMENT = 82,
DECIMAL_LITERAL = 83
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
};
enum {
......@@ -1097,8 +1098,9 @@ class TorqueParser : public antlr4::Parser {
DiagnosticStatementContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* ASSERT();
ExpressionContext* expression();
antlr4::tree::TerminalNode* ASSERT_TOKEN();
antlr4::tree::TerminalNode* CHECK_TOKEN();
antlr4::tree::TerminalNode* UNREACHABLE_TOKEN();
antlr4::tree::TerminalNode* DEBUG_TOKEN();
......
......@@ -748,14 +748,14 @@ antlrcpp::Any AstGenerator::visitConditionalExpression(
antlrcpp::Any AstGenerator::visitDiagnosticStatement(
TorqueParser::DiagnosticStatementContext* context) {
if (context->ASSERT()) {
if (context->ASSERT_TOKEN() || context->CHECK_TOKEN()) {
size_t a = context->expression()->start->getStartIndex();
size_t b = context->expression()->stop->getStopIndex();
antlr4::misc::Interval interval(a, b);
std::string source = source_file_context_->stream->getText(interval);
return implicit_cast<Statement*>(RegisterNode(new AssertStatement{
Pos(context), context->expression()->accept(this).as<Expression*>(),
source}));
Pos(context), context->ASSERT_TOKEN() != nullptr,
context->expression()->accept(this).as<Expression*>(), source}));
} else if (context->UNREACHABLE_TOKEN()) {
return implicit_cast<Statement*>(
RegisterNode(new DebugStatement{Pos(context), "unreachable", true}));
......
......@@ -427,8 +427,13 @@ struct DebugStatement : Statement {
struct AssertStatement : Statement {
DEFINE_AST_NODE_LEAF_BOILERPLATE(AssertStatement)
AssertStatement(SourcePosition p, Expression* e, const std::string& s)
: Statement(kKind, p), expression(e), source(s) {}
AssertStatement(SourcePosition pos, bool debug_only, Expression* expression,
std::string source)
: Statement(kKind, pos),
debug_only(debug_only),
expression(expression),
source(std::move(source)) {}
bool debug_only;
Expression* expression;
std::string source;
};
......
......@@ -115,9 +115,11 @@ class DeclarationVisitor : public FileVisitor {
void Visit(DebugStatement* stmt) {}
void Visit(AssertStatement* stmt) {
bool do_check = !stmt->debug_only;
#if defined(DEBUG)
DeclareExpressionForBranch(stmt->expression);
do_check = true;
#endif
if (do_check) DeclareExpressionForBranch(stmt->expression);
}
void Visit(VarDeclarationStatement* stmt) {
......
......@@ -692,46 +692,50 @@ const Type* ImplementationVisitor::Visit(DebugStatement* stmt) {
}
const Type* ImplementationVisitor::Visit(AssertStatement* stmt) {
bool do_check = !stmt->debug_only;
#if defined(DEBUG)
// CSA_ASSERT & co. are not used here on purpose for two reasons. First,
// Torque allows and handles two types of expressions in the if protocol
// automagically, ones that return TNode<BoolT> and those that use the
// BranchIf(..., Label* true, Label* false) idiom. Because the machinery to
// handle this is embedded in the expression handling and to it's not possible
// to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH isn't trivial
// up-front. Secondly, on failure, the assert text should be the corresponding
// Torque code, not the -gen.cc code, which would be the case when using
// CSA_ASSERT_XXX.
Label* true_label = nullptr;
Label* false_label = nullptr;
Declarations::NodeScopeActivator scope(declarations(), stmt->expression);
true_label = declarations()->LookupLabel(kTrueLabelName);
GenerateLabelDefinition(true_label);
false_label = declarations()->LookupLabel(kFalseLabelName);
GenerateLabelDefinition(false_label);
VisitResult expression_result = Visit(stmt->expression);
if (expression_result.type() == GetTypeOracle().GetBoolType()) {
GenerateBranch(expression_result, true_label, false_label);
} else {
if (expression_result.type() != GetTypeOracle().GetNeverType()) {
std::stringstream s;
s << "unexpected return type " << expression_result.type()
<< " for branch expression";
ReportError(s.str());
do_check = true;
#endif
if (do_check) {
// CSA_ASSERT & co. are not used here on purpose for two reasons. First,
// Torque allows and handles two types of expressions in the if protocol
// automagically, ones that return TNode<BoolT> and those that use the
// BranchIf(..., Label* true, Label* false) idiom. Because the machinery to
// handle this is embedded in the expression handling and to it's not
// possible to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH
// isn't trivial up-front. Secondly, on failure, the assert text should be
// the corresponding Torque code, not the -gen.cc code, which would be the
// case when using CSA_ASSERT_XXX.
Label* true_label = nullptr;
Label* false_label = nullptr;
Declarations::NodeScopeActivator scope(declarations(), stmt->expression);
true_label = declarations()->LookupLabel(kTrueLabelName);
GenerateLabelDefinition(true_label);
false_label = declarations()->LookupLabel(kFalseLabelName);
GenerateLabelDefinition(false_label);
VisitResult expression_result = Visit(stmt->expression);
if (expression_result.type() == GetTypeOracle().GetBoolType()) {
GenerateBranch(expression_result, true_label, false_label);
} else {
if (expression_result.type() != GetTypeOracle().GetNeverType()) {
std::stringstream s;
s << "unexpected return type " << expression_result.type()
<< " for branch expression";
ReportError(s.str());
}
}
}
GenerateLabelBind(false_label);
GenerateIndent();
source_out() << "Print(\""
<< "assert '" << stmt->source << "' failed at "
<< PositionAsString(stmt->pos) << "\");" << std::endl;
GenerateIndent();
source_out() << "Unreachable();" << std::endl;
GenerateLabelBind(false_label);
GenerateIndent();
source_out() << "Print(\""
<< "assert '" << stmt->source << "' failed at "
<< PositionAsString(stmt->pos) << "\");" << std::endl;
GenerateIndent();
source_out() << "Unreachable();" << std::endl;
GenerateLabelBind(true_label);
#endif
GenerateLabelBind(true_label);
}
return GetTypeOracle().GetVoidType();
}
......
......@@ -36,20 +36,20 @@ module test {
}
macro TestConstexpr1() {
assert(convert<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
check(convert<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
}
macro TestConstexprIf() {
assert(ElementsKindTestHelper1(UINT8_ELEMENTS));
assert(ElementsKindTestHelper1(UINT16_ELEMENTS));
assert(!ElementsKindTestHelper1(UINT32_ELEMENTS));
check(ElementsKindTestHelper1(UINT8_ELEMENTS));
check(ElementsKindTestHelper1(UINT16_ELEMENTS));
check(!ElementsKindTestHelper1(UINT32_ELEMENTS));
}
macro TestConstexprReturn() {
assert(convert<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
assert(convert<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
assert(!convert<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
assert(convert<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
check(convert<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
check(convert<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
check(!convert<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
check(convert<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
}
macro TestGotoLabel(): Boolean {
......@@ -66,7 +66,7 @@ module test {
LabelTestHelper2() otherwise Label2;
}
label Label2(smi: Smi) {
assert(smi == 42);
check(smi == 42);
return True;
}
}
......@@ -76,8 +76,8 @@ module test {
LabelTestHelper3() otherwise Label3;
}
label Label3(str: String, smi: Smi) {
assert(str == 'foo');
assert(smi == 7);
check(str == 'foo');
check(smi == 7);
return True;
}
}
......@@ -91,10 +91,10 @@ module test {
}
macro TestBuiltinSpecialization(c: Context) {
assert(GenericBuiltinTest<Smi>(c, 0) == Null);
assert(GenericBuiltinTest<Smi>(c, 1) == Null);
assert(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
assert(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
check(GenericBuiltinTest<Smi>(c, 0) == Null);
check(GenericBuiltinTest<Smi>(c, 1) == Null);
check(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
check(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
}
macro LabelTestHelper4(flag: constexpr bool): never labels Label4, Label5 {
......@@ -143,16 +143,15 @@ module test {
macro TestMacroSpecialization() {
try {
if (True == False) goto Fail; // Silence warnings in release build
assert(GenericMacroTest<Smi>(0) == Undefined);
assert(GenericMacroTest<Smi>(1) == Undefined);
assert(GenericMacroTest<Object>(Null) == Null);
assert(GenericMacroTest<Object>(False) == False);
assert(GenericMacroTest<Object>(True) == True);
assert(GenericMacroTestWithLabels<Smi>(0) otherwise Fail == Undefined);
assert(GenericMacroTestWithLabels<Smi>(0) otherwise Fail == Undefined);
assert(GenericMacroTestWithLabels<Object>(Null) otherwise Fail == Null);
assert(GenericMacroTestWithLabels<Object>(False) otherwise Fail == False);
check(GenericMacroTest<Smi>(0) == Undefined);
check(GenericMacroTest<Smi>(1) == Undefined);
check(GenericMacroTest<Object>(Null) == Null);
check(GenericMacroTest<Object>(False) == False);
check(GenericMacroTest<Object>(True) == True);
check(GenericMacroTestWithLabels<Smi>(0) otherwise Fail == Undefined);
check(GenericMacroTestWithLabels<Smi>(0) otherwise Fail == Undefined);
check(GenericMacroTestWithLabels<Object>(Null) otherwise Fail == Null);
check(GenericMacroTestWithLabels<Object>(False) otherwise Fail == False);
}
label Fail {
unreachable;
......@@ -168,9 +167,9 @@ module test {
macro TestFunctionPointers(context : Context) : Boolean {
let fptr : builtin(Context, Smi) => Smi = TestHelperPlus1;
assert(fptr(context, 42) == 43);
check(fptr(context, 42) == 43);
fptr = TestHelperPlus2;
assert(fptr(context, 42) == 44);
check(fptr(context, 42) == 44);
return True;
}
......@@ -184,10 +183,10 @@ module test {
let fptr1: builtin(Context, Smi) => Object = GenericBuiltinTest<Smi>;
let fptr2: builtin(Context, Object) => Object = GenericBuiltinTest<Object>;
assert(fptr1(c, 0) == Null);
assert(fptr1(c, 1) == Null);
assert(fptr2(c, Undefined) == Undefined);
assert(fptr2(c, Undefined) == Undefined);
check(fptr1(c, 0) == Null);
check(fptr1(c, 1) == Null);
check(fptr2(c, Undefined) == Undefined);
check(fptr2(c, Undefined) == Undefined);
}
type SmiToSmi = builtin(Smi) => Smi;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment