Commit 74a0ad7d authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque] Implement intrinsics support

Also add the first intrinsic and usage of it: %RawCast

Bug: v8:7793
Change-Id: Id1e3288e8bab6adb510731076a39590e8fd156be
Reviewed-on: https://chromium-review.googlesource.com/c/1344152
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57692}
parent d8c471ff
......@@ -62,6 +62,11 @@ type SloppyArgumentsElements extends FixedArray
type NumberDictionary extends HeapObject
generates 'TNode<NumberDictionary>';
// RawCasts should *never* be used anywhere in Torque code except for
// in Torque-based UnsafeCast operators preceeded by an appropriate
// type assert()
intrinsic %RawCast<A: type>(o: Object): A;
type NativeContextSlot generates 'TNode<IntPtrT>' constexpr 'int32_t';
const ARRAY_JOIN_STACK_INDEX: constexpr NativeContextSlot
generates 'Context::ARRAY_JOIN_STACK_INDEX';
......@@ -835,15 +840,6 @@ UnsafeCast<String>(o: Object): String {
return UnsafeCastObjectToString(o);
}
// RawCasts should *never* be used anywhere in Torque code except for
// in Torque-based UnsafeCast operators preceeded by an appropriate
// type check().
extern macro RawCastObjectToJSFunction(Object): JSFunction;
extern macro RawCastObjectToJSArgumentsObjectWithLength(Object):
JSArgumentsObjectWithLength;
extern macro RawCastObjectToFastJSArray(Object): FastJSArray;
extern macro RawCastObjectToFastJSArrayForCopy(Object): FastJSArrayForCopy;
macro BranchIfJSArgumentsObjectWithLength(implicit context: Context)(o: Object):
never
labels True, False {
......@@ -859,7 +855,7 @@ macro BranchIfJSArgumentsObjectWithLength(implicit context: Context)(o: Object):
UnsafeCast<JSArgumentsObjectWithLength>(implicit context: Context)(o: Object):
JSArgumentsObjectWithLength {
assert(BranchIfJSArgumentsObjectWithLength(o));
return RawCastObjectToJSArgumentsObjectWithLength(o);
return %RawCast<JSArgumentsObjectWithLength>(o);
}
Cast<JSArgumentsObjectWithLength>(implicit context: Context)(o: Object):
......@@ -874,7 +870,7 @@ Cast<JSArgumentsObjectWithLength>(implicit context: Context)(o: Object):
UnsafeCast<FastJSArray>(implicit context: Context)(o: Object): FastJSArray {
assert(BranchIfFastJSArray(o, context));
return RawCastObjectToFastJSArray(o);
return %RawCast<FastJSArray>(o);
}
Cast<FastJSArray>(implicit context: Context)(o: Object): FastJSArray
......@@ -898,7 +894,7 @@ Cast<FastJSArray>(implicit context: Context)(ho: HeapObject): FastJSArray
UnsafeCast<FastJSArrayForCopy>(implicit context: Context)(o: Object):
FastJSArrayForCopy {
assert(BranchIfFastJSArrayForCopy(o, context));
return RawCastObjectToFastJSArrayForCopy(o);
return %RawCast<FastJSArrayForCopy>(o);
}
Cast<FastJSArrayForCopy>(implicit context: Context)(o: Object):
......@@ -913,7 +909,7 @@ Cast<FastJSArrayForCopy>(implicit context: Context)(o: Object):
UnsafeCast<JSFunction>(implicit context: Context)(o: Object): JSFunction {
assert(IsJSFunction(Cast<HeapObject>(o) otherwise unreachable));
return RawCastObjectToJSFunction(o);
return %RawCast<JSFunction>(o);
}
Cast<JSFunction>(implicit context: Context)(o: Object): JSFunction
......
......@@ -403,23 +403,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
return CAST(p_o);
}
TNode<JSArgumentsObjectWithLength> RawCastObjectToJSArgumentsObjectWithLength(
TNode<Object> p_o) {
return TNode<JSArgumentsObjectWithLength>::UncheckedCast(p_o);
}
TNode<JSArray> RawCastObjectToFastJSArray(TNode<Object> p_o) {
return TNode<JSArray>::UncheckedCast(p_o);
}
TNode<JSArray> RawCastObjectToFastJSArrayForCopy(TNode<Object> p_o) {
return TNode<JSArray>::UncheckedCast(p_o);
}
TNode<JSFunction> RawCastObjectToJSFunction(TNode<Object> p_o) {
return TNode<JSFunction>::UncheckedCast(p_o);
}
Node* MatchesParameterMode(Node* value, ParameterMode mode);
#define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName) \
......
......@@ -18,6 +18,7 @@
#include "src/heap/heap.h"
#include "src/machine-type.h"
#include "src/objects.h"
#include "src/objects/arguments.h"
#include "src/objects/data-handler.h"
#include "src/objects/map.h"
#include "src/objects/maybe-object.h"
......
......@@ -757,6 +757,7 @@ class ZoneForwardList;
V(HeapNumber) \
V(InternalizedString) \
V(JSArgumentsObject) \
V(JSArgumentsObjectWithLength) \
V(JSArray) \
V(JSArrayBuffer) \
V(JSArrayBufferView) \
......@@ -927,6 +928,7 @@ class ZoneForwardList;
V(GlobalDictionary, GLOBAL_DICTIONARY_TYPE) \
V(HeapNumber, HEAP_NUMBER_TYPE) \
V(JSArgumentsObject, JS_ARGUMENTS_TYPE) \
V(JSArgumentsObjectWithLength, JS_ARGUMENTS_TYPE) \
V(JSArray, JS_ARRAY_TYPE) \
V(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) \
V(JSArrayIterator, JS_ARRAY_ITERATOR_TYPE) \
......
......@@ -19,6 +19,7 @@ namespace torque {
#define AST_EXPRESSION_NODE_KIND_LIST(V) \
V(CallExpression) \
V(IntrinsicCallExpression) \
V(StructExpression) \
V(LogicalOrExpression) \
V(LogicalAndExpression) \
......@@ -71,7 +72,8 @@ namespace torque {
V(TorqueBuiltinDeclaration) \
V(ExternalMacroDeclaration) \
V(ExternalBuiltinDeclaration) \
V(ExternalRuntimeDeclaration)
V(ExternalRuntimeDeclaration) \
V(IntrinsicDeclaration)
#define AST_NODE_KIND_LIST(V) \
AST_EXPRESSION_NODE_KIND_LIST(V) \
......@@ -201,6 +203,20 @@ struct IdentifierExpression : LocationExpression {
std::vector<TypeExpression*> generic_arguments;
};
struct IntrinsicCallExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicCallExpression)
IntrinsicCallExpression(SourcePosition pos, std::string name,
std::vector<TypeExpression*> generic_arguments,
std::vector<Expression*> arguments)
: Expression(kKind, pos),
name(std::move(name)),
generic_arguments(std::move(generic_arguments)),
arguments(std::move(arguments)) {}
std::string name;
std::vector<TypeExpression*> generic_arguments;
std::vector<Expression*> arguments;
};
struct CallExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(CallExpression)
CallExpression(SourcePosition pos, IdentifierExpression* callee,
......@@ -666,6 +682,14 @@ struct ExternalMacroDeclaration : MacroDeclaration {
std::string external_assembler_name;
};
struct IntrinsicDeclaration : CallableNode {
DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicDeclaration)
IntrinsicDeclaration(SourcePosition pos, std::string name,
ParameterList parameters, TypeExpression* return_type)
: CallableNode(kKind, pos, false, std::move(name), std::move(parameters),
return_type, {}) {}
};
struct TorqueMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration)
TorqueMacroDeclaration(SourcePosition pos, bool transitioning,
......
......@@ -128,29 +128,85 @@ void CSAGenerator::EmitInstruction(
}
}
void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
Stack<std::string>* stack) {
std::vector<std::string> constexpr_arguments =
instruction.constexpr_arguments;
std::vector<std::string> args;
TypeVector parameter_types =
instruction.macro->signature().parameter_types.types;
void CSAGenerator::ProcessArgumentsCommon(
const TypeVector& parameter_types, std::vector<std::string>* args,
std::vector<std::string>* constexpr_arguments, Stack<std::string>* stack) {
for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) {
const Type* type = *it;
VisitResult arg;
if (type->IsConstexpr()) {
args.push_back(std::move(constexpr_arguments.back()));
constexpr_arguments.pop_back();
args->push_back(std::move(constexpr_arguments->back()));
constexpr_arguments->pop_back();
} else {
std::stringstream s;
size_t slot_count = LoweredSlotCount(type);
VisitResult arg = VisitResult(type, stack->TopRange(slot_count));
EmitCSAValue(arg, *stack, s);
args.push_back(s.str());
args->push_back(s.str());
stack->PopMany(slot_count);
}
}
std::reverse(args.begin(), args.end());
std::reverse(args->begin(), args->end());
}
void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
Stack<std::string>* stack) {
std::vector<std::string> constexpr_arguments =
instruction.constexpr_arguments;
std::vector<std::string> args;
TypeVector parameter_types =
instruction.intrinsic->signature().parameter_types.types;
ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
Stack<std::string> pre_call_stack = *stack;
const Type* return_type = instruction.intrinsic->signature().return_type;
std::vector<std::string> results;
for (const Type* type : LowerType(return_type)) {
results.push_back(FreshNodeName());
stack->Push(results.back());
out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
<< stack->Top() << ";\n";
out_ << " USE(" << stack->Top() << ");\n";
}
out_ << " ";
if (return_type->IsStructType()) {
out_ << "std::tie(";
PrintCommaSeparatedList(out_, results);
out_ << ") = ";
} else {
if (results.size() == 1) {
out_ << results[0] << " = ";
}
}
if (instruction.intrinsic->ExternalName() == "%RawCast") {
if (!return_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
ReportError("%RawCast must cast to subtype of Object");
}
out_ << "TORQUE_CAST";
} else {
ReportError("no built in intrinsic with name " +
instruction.intrinsic->ExternalName());
}
out_ << "(";
PrintCommaSeparatedList(out_, args);
if (return_type->IsStructType()) {
out_ << ").Flatten();\n";
} else {
out_ << ");\n";
}
}
void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
Stack<std::string>* stack) {
std::vector<std::string> constexpr_arguments =
instruction.constexpr_arguments;
std::vector<std::string> args;
TypeVector parameter_types =
instruction.macro->signature().parameter_types.types;
ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
Stack<std::string> pre_call_stack = *stack;
const Type* return_type = instruction.macro->signature().return_type;
......@@ -196,22 +252,7 @@ void CSAGenerator::EmitInstruction(
std::vector<std::string> args;
TypeVector parameter_types =
instruction.macro->signature().parameter_types.types;
for (auto it = parameter_types.rbegin(); it != parameter_types.rend(); ++it) {
const Type* type = *it;
VisitResult arg;
if (type->IsConstexpr()) {
args.push_back(std::move(constexpr_arguments.back()));
constexpr_arguments.pop_back();
} else {
std::stringstream s;
size_t slot_count = LoweredSlotCount(type);
VisitResult arg = VisitResult(type, stack->TopRange(slot_count));
EmitCSAValue(arg, *stack, s);
args.push_back(s.str());
stack->PopMany(slot_count);
}
}
std::reverse(args.begin(), args.end());
ProcessArgumentsCommon(parameter_types, &args, &constexpr_arguments, stack);
Stack<std::string> pre_call_stack = *stack;
std::vector<std::string> results;
......
......@@ -45,6 +45,11 @@ class CSAGenerator {
return "block" + std::to_string(block->id());
}
void ProcessArgumentsCommon(const TypeVector& parameter_types,
std::vector<std::string>* args,
std::vector<std::string>* constexpr_arguments,
Stack<std::string>* stack);
Stack<std::string> EmitBlock(const Block* block);
void EmitInstruction(const Instruction& instruction,
Stack<std::string>* stack);
......
......@@ -45,6 +45,7 @@ class Declarable {
kMacro,
kBuiltin,
kRuntimeFunction,
kIntrinsic,
kGeneric,
kTypeAlias,
kExternConstant,
......@@ -53,6 +54,7 @@ class Declarable {
Kind kind() const { return kind_; }
bool IsNamespace() const { return kind() == kNamespace; }
bool IsMacro() const { return kind() == kMacro; }
bool IsIntrinsic() const { return kind() == kIntrinsic; }
bool IsBuiltin() const { return kind() == kBuiltin; }
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
bool IsGeneric() const { return kind() == kGeneric; }
......@@ -62,7 +64,7 @@ class Declarable {
bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
bool IsScope() const { return IsNamespace() || IsCallable(); }
bool IsCallable() const {
return IsMacro() || IsBuiltin() || IsRuntimeFunction();
return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic();
}
virtual const char* type_name() const { return "<<unknown>>"; }
Scope* ParentScope() const { return parent_scope_; }
......@@ -329,6 +331,21 @@ class RuntimeFunction : public Callable {
transitioning, base::nullopt) {}
};
class Intrinsic : public Callable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic);
private:
friend class Declarations;
Intrinsic(std::string name, const Signature& signature)
: Callable(Declarable::kIntrinsic, name, name, signature, false,
base::nullopt) {
if (signature.parameter_types.var_args) {
ReportError("Varargs are not supported for intrinsics.");
}
}
};
class Generic : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Generic, generic);
......
......@@ -142,6 +142,12 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
decl->transitioning, body, decl->op);
}
void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
const Signature& signature,
base::Optional<Statement*> body) {
Declarations::DeclareIntrinsic(decl->name, signature);
}
void DeclarationVisitor::Visit(ConstDeclaration* decl) {
Declarations::DeclareNamespaceConstant(
decl->name, Declarations::GetType(decl->type), decl->expression);
......@@ -290,7 +296,9 @@ Signature DeclarationVisitor::MakeSpecializedSignature(
}
Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
if (!key.generic->declaration()->body) {
if (!key.generic->declaration()->body &&
IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
nullptr) {
ReportError("missing specialization of ", key.generic->name(),
" with types <", key.specialized_types, "> declared at ",
key.generic->pos());
......@@ -298,7 +306,7 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
CurrentScope::Scope generic_scope(key.generic->ParentScope());
Callable* result =
Specialize(key, key.generic->declaration()->callable, base::nullopt,
*key.generic->declaration()->body);
key.generic->declaration()->body);
CurrentScope::Scope callable_scope(result);
DeclareSpecializedTypes(key);
return result;
......@@ -306,7 +314,8 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
Callable* DeclarationVisitor::Specialize(
const SpecializationKey& key, CallableNode* declaration,
base::Optional<const CallableNodeSignature*> signature, Statement* body) {
base::Optional<const CallableNodeSignature*> signature,
base::Optional<Statement*> body) {
// TODO(tebbi): The error should point to the source position where the
// instantiation was requested.
CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
......@@ -344,11 +353,13 @@ Callable* DeclarationVisitor::Specialize(
if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
callable = Declarations::CreateMacro(generated_name, readable_name.str(),
base::nullopt, type_signature,
declaration->transitioning, body);
declaration->transitioning, *body);
} else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
} else {
BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
type_signature, body);
type_signature, *body);
}
key.generic->AddSpecialization(key.specialized_types, callable);
return callable;
......
......@@ -69,6 +69,8 @@ class DeclarationVisitor : public FileVisitor {
base::Optional<Statement*> body);
void Visit(TorqueMacroDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
void Visit(IntrinsicDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
void Visit(CallableNode* decl, const Signature& signature,
base::Optional<Statement*> body);
......@@ -84,7 +86,7 @@ class DeclarationVisitor : public FileVisitor {
Callable* SpecializeImplicit(const SpecializationKey& key);
Callable* Specialize(const SpecializationKey& key, CallableNode* declaration,
base::Optional<const CallableNodeSignature*> signature,
Statement* body);
base::Optional<Statement*> body);
private:
void DeclareSpecializedTypes(const SpecializationKey& key);
......
......@@ -208,6 +208,20 @@ Macro* Declarations::DeclareMacro(
return macro;
}
Intrinsic* Declarations::CreateIntrinsic(const std::string& name,
const Signature& signature) {
Intrinsic* result = RegisterDeclarable(std::unique_ptr<Intrinsic>(
new Intrinsic(std::move(name), std::move(signature))));
return result;
}
Intrinsic* Declarations::DeclareIntrinsic(const std::string& name,
const Signature& signature) {
Intrinsic* result = CreateIntrinsic(std::move(name), std::move(signature));
Declare(name, result);
return result;
}
Builtin* Declarations::CreateBuiltin(std::string external_name,
std::string readable_name,
Builtin::Kind kind, Signature signature,
......
......@@ -97,6 +97,12 @@ class Declarations {
const Signature& signature, bool transitioning,
base::Optional<Statement*> body, base::Optional<std::string> op = {});
static Intrinsic* CreateIntrinsic(const std::string& name,
const Signature& signature);
static Intrinsic* DeclareIntrinsic(const std::string& name,
const Signature& signature);
static Builtin* CreateBuiltin(std::string external_name,
std::string readable_name, Builtin::Kind kind,
Signature signature, bool transitioning,
......
......@@ -1809,6 +1809,11 @@ VisitResult ImplementationVisitor::GenerateCall(
// we should assert slot_count == 1 here.
return VisitResult(return_type, assembler().TopRange(slot_count));
}
} else if (auto* intrinsic = Intrinsic::DynamicCast(callable)) {
assembler().Emit(CallIntrinsicInstruction{intrinsic, constexpr_arguments});
size_t return_slot_count =
LoweredSlotCount(intrinsic->signature().return_type);
return VisitResult(return_type, assembler().TopRange(return_slot_count));
} else {
UNREACHABLE();
}
......@@ -1837,6 +1842,16 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
}
}
VisitResult ImplementationVisitor::Visit(IntrinsicCallExpression* expr) {
StackScope scope(this);
Arguments arguments;
TypeVector specialization_types = GetTypeVector(expr->generic_arguments);
for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg));
return scope.Yield(
GenerateCall(expr->name, arguments, specialization_types, false));
}
void ImplementationVisitor::GenerateBranch(const VisitResult& condition,
Block* true_block,
Block* false_block) {
......@@ -2013,6 +2028,7 @@ void ImplementationVisitor::Visit(Declarable* declarable) {
case Declarable::kNamespaceConstant:
return Visit(NamespaceConstant::cast(declarable));
case Declarable::kRuntimeFunction:
case Declarable::kIntrinsic:
case Declarable::kExternConstant:
case Declarable::kNamespace:
case Declarable::kGeneric:
......
......@@ -233,6 +233,7 @@ class ImplementationVisitor : public FileVisitor {
void Visit(NamespaceConstant* decl);
VisitResult Visit(CallExpression* expr, bool is_tail = false);
VisitResult Visit(IntrinsicCallExpression* intrinsic);
const Type* Visit(TailCallStatement* stmt);
VisitResult Visit(ConditionalExpression* expr);
......
......@@ -85,6 +85,25 @@ void InstructionBase::InvalidateTransientTypes(
}
}
void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {
std::vector<const Type*> parameter_types =
LowerParameterTypes(intrinsic->signature().parameter_types);
for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
const Type* arg_type = stack->Pop();
const Type* parameter_type = parameter_types.back();
parameter_types.pop_back();
if (arg_type != parameter_type) {
ReportError("parameter ", i, ": expected type ", *parameter_type,
" but found type ", *arg_type);
}
}
if (intrinsic->IsTransitioning()) {
InvalidateTransientTypes(stack);
}
stack->PushMany(LowerType(intrinsic->signature().return_type));
}
void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {
std::vector<const Type*> parameter_types =
......@@ -98,7 +117,6 @@ void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
" but found type ", *arg_type);
}
}
if (!parameter_types.empty()) ReportError("missing arguments");
if (macro->IsTransitioning()) {
InvalidateTransientTypes(stack);
......@@ -126,7 +144,6 @@ void CallCsaMacroAndBranchInstruction::TypeInstruction(
" but found type ", *arg_type);
}
}
if (!parameter_types.empty()) ReportError("missing arguments");
if (label_blocks.size() != macro->signature().labels.size()) {
ReportError("wrong number of labels");
......
......@@ -19,6 +19,7 @@ namespace torque {
class Block;
class Builtin;
class ControlFlowGraph;
class Intrinsic;
class Macro;
class NamespaceConstant;
class RuntimeFunction;
......@@ -30,6 +31,7 @@ class RuntimeFunction;
V(PushUninitializedInstruction) \
V(PushCodePointerInstruction) \
V(CallCsaMacroInstruction) \
V(CallIntrinsicInstruction) \
V(NamespaceConstantInstruction) \
V(CallCsaMacroAndBranchInstruction) \
V(CallBuiltinInstruction) \
......@@ -187,6 +189,16 @@ struct NamespaceConstantInstruction : InstructionBase {
NamespaceConstant* constant;
};
struct CallIntrinsicInstruction : InstructionBase {
TORQUE_INSTRUCTION_BOILERPLATE()
CallIntrinsicInstruction(Intrinsic* intrinsic,
std::vector<std::string> constexpr_arguments)
: intrinsic(intrinsic), constexpr_arguments(constexpr_arguments) {}
Intrinsic* intrinsic;
std::vector<std::string> constexpr_arguments;
};
struct CallCsaMacroInstruction : InstructionBase {
TORQUE_INSTRUCTION_BOILERPLATE()
CallCsaMacroInstruction(Macro* macro,
......
......@@ -269,6 +269,17 @@ base::Optional<ParseResult> MakeBinaryOperator(
std::vector<Statement*>{})};
}
base::Optional<ParseResult> MakeIntrinsicDeclarationCallExpression(
ParseResultIterator* child_results) {
auto callee = child_results->NextAs<std::string>();
auto generic_arguments =
child_results->NextAs<std::vector<TypeExpression*>>();
auto args = child_results->NextAs<std::vector<Expression*>>();
Expression* result =
MakeNode<IntrinsicCallExpression>(callee, generic_arguments, args);
return ParseResult{result};
}
base::Optional<ParseResult> MakeUnaryOperator(
ParseResultIterator* child_results) {
auto op = child_results->NextAs<std::string>();
......@@ -382,6 +393,25 @@ base::Optional<ParseResult> MakeExternalMacro(
return ParseResult{result};
}
base::Optional<ParseResult> MakeIntrinsicDeclaration(
ParseResultIterator* child_results) {
auto name = child_results->NextAs<std::string>();
auto generic_parameters = child_results->NextAs<GenericParameters>();
LintGenericParameters(generic_parameters);
auto args = child_results->NextAs<ParameterList>();
auto return_type = child_results->NextAs<TypeExpression*>();
IntrinsicDeclaration* macro =
MakeNode<IntrinsicDeclaration>(name, args, return_type);
Declaration* result;
if (generic_parameters.empty()) {
result = MakeNode<StandardDeclaration>(macro, base::nullopt);
} else {
result = MakeNode<GenericDeclaration>(macro, generic_parameters);
}
return ParseResult{result};
}
base::Optional<ParseResult> MakeTorqueMacroDeclaration(
ParseResultIterator* child_results) {
auto transitioning = child_results->NextAs<bool>();
......@@ -1025,6 +1055,16 @@ struct TorqueGrammar : Grammar {
return true;
}
static bool MatchIntrinsicName(InputPosition* pos) {
InputPosition current = *pos;
if (!MatchString("%", &current)) return false;
if (!MatchChar(std::isalpha, &current)) return false;
while (MatchChar(std::isalnum, &current) || MatchString("_", pos)) {
}
*pos = current;
return true;
}
static bool MatchStringLiteral(InputPosition* pos) {
InputPosition current = *pos;
if (MatchString("\"", &current)) {
......@@ -1088,6 +1128,10 @@ struct TorqueGrammar : Grammar {
// Result: std::string
Symbol identifier = {Rule({Pattern(MatchIdentifier)}, YieldMatchedInput)};
// Result: std::string
Symbol intrinsicName = {
Rule({Pattern(MatchIntrinsicName)}, YieldMatchedInput)};
// Result: std::string
Symbol stringLiteral = {
Rule({Pattern(MatchStringLiteral)}, YieldMatchedInput)};
......@@ -1237,9 +1281,16 @@ struct TorqueGrammar : Grammar {
Symbol callExpression = {Rule(
{&identifierExpression, &argumentList, optionalOtherwise}, MakeCall)};
// Result: Expression*
Symbol IntrinsicCallExpression = {Rule(
{&intrinsicName, TryOrDefault<TypeList>(&genericSpecializationTypeList),
&argumentList},
MakeIntrinsicDeclarationCallExpression)};
// Result: Expression*
Symbol primaryExpression = {
Rule({&callExpression}),
Rule({&IntrinsicCallExpression}),
Rule({&locationExpression},
CastParseResult<LocationExpression*, Expression*>),
Rule({&decimalLiteral}, MakeNumberLiteralExpression),
......@@ -1431,6 +1482,10 @@ struct TorqueGrammar : Grammar {
MakeTypeDeclaration),
Rule({Token("type"), &identifier, Token("="), &type, Token(";")},
MakeTypeAliasDeclaration),
Rule({Token("intrinsic"), &intrinsicName,
TryOrDefault<GenericParameters>(&genericParameters),
&parameterListNoVararg, &optionalReturnType, Token(";")},
MakeIntrinsicDeclaration),
Rule({Token("extern"), CheckIf(Token("transitioning")),
Optional<std::string>(
Sequence({Token("operator"), &externalString})),
......
......@@ -204,7 +204,9 @@ void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
if (i > 0) os << ", ";
}
if (with_names && !sig.parameter_names.empty()) {
os << sig.parameter_names[i] << ": ";
if (i < sig.parameter_names.size()) {
os << sig.parameter_names[i] << ": ";
}
}
os << *sig.parameter_types.types[i];
}
......
......@@ -47,6 +47,7 @@ def preprocess(input):
return input
def postprocess(output):
output = re.sub(r'% RawCast', r'%RawCast', output)
output = re.sub(r'\/\*COxp\*\/', r'constexpr', output)
output = re.sub(r'(\S+)\s*: type([,>])', r'\1: type\2', output)
output = re.sub(r'(\n\s*)labels( [A-Z])', r'\1 labels\2', output)
......
......@@ -26,7 +26,7 @@ syn keyword torqueBranch break continue goto
syn keyword torqueConditional if else typeswitch otherwise
syn match torqueConstant /\v<[A-Z][A-Z0-9_]+>/
syn match torqueConstant /\v<k[A-Z][A-Za-z0-9]*>/
syn keyword torqueFunction macro builtin runtime
syn keyword torqueFunction macro builtin runtime intrinsic
syn keyword torqueKeyword cast convert from_constexpr min max unsafe_cast
syn keyword torqueLabel case
syn keyword torqueMatching try label catch
......
......@@ -65,7 +65,7 @@
},
{
"name": "keyword.other.torque",
"match": "\\b(constexpr|module|macro|builtin|runtime|javascript|implicit|deferred|label|labels|tail|let|generates|type|extends|extern|const|typeswitch|case|transient|transitioning)\\b"
"match": "\\b(constexpr|module|macro|builtin|runtime|intrinsic|javascript|implicit|deferred|label|labels|tail|let|generates|type|extends|extern|const|typeswitch|case|transient|transitioning)\\b"
},
{
"name": "keyword.operator.torque",
......
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