declaration-visitor.cc 16.2 KB
Newer Older
1 2 3 4 5
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/torque/declaration-visitor.h"
6

7
#include "src/torque/ast.h"
8
#include "src/torque/kythe-data.h"
9
#include "src/torque/server-data.h"
10
#include "src/torque/type-inference.h"
11
#include "src/torque/type-visitor.h"
12 13 14 15 16

namespace v8 {
namespace internal {
namespace torque {

17 18 19 20 21 22 23 24 25 26
Namespace* GetOrCreateNamespace(const std::string& name) {
  std::vector<Namespace*> existing_namespaces = FilterDeclarables<Namespace>(
      Declarations::TryLookupShallow(QualifiedName(name)));
  if (existing_namespaces.empty()) {
    return Declarations::DeclareNamespace(name);
  }
  DCHECK_EQ(1, existing_namespaces.size());
  return existing_namespaces.front();
}

27
void PredeclarationVisitor::Predeclare(Declaration* decl) {
28 29 30 31 32 33 34 35 36
  CurrentSourcePosition::Scope scope(decl->pos);
  switch (decl->kind) {
#define ENUM_ITEM(name)        \
  case AstNode::Kind::k##name: \
    return Predeclare(name::cast(decl));
    AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
    case AstNode::Kind::kNamespaceDeclaration:
      return Predeclare(NamespaceDeclaration::cast(decl));
37 38 39 40 41
    case AstNode::Kind::kGenericCallableDeclaration:
      return Predeclare(GenericCallableDeclaration::cast(decl));
    case AstNode::Kind::kGenericTypeDeclaration:
      return Predeclare(GenericTypeDeclaration::cast(decl));

42
    default:
43
      // Only processes type declaration nodes, namespaces and generics.
44 45 46 47
      break;
  }
}

48
void DeclarationVisitor::Visit(Declaration* decl) {
49
  CurrentSourcePosition::Scope scope(decl->pos);
50 51 52 53 54 55 56 57 58 59 60
  switch (decl->kind) {
#define ENUM_ITEM(name)        \
  case AstNode::Kind::k##name: \
    return Visit(name::cast(decl));
    AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
    default:
      UNIMPLEMENTED();
  }
}

61
Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
62 63 64
                                           std::string external_name,
                                           std::string readable_name,
                                           Signature signature,
65
                                           base::Optional<Statement*> body) {
66
  const bool javascript = decl->javascript_linkage;
67
  const bool varargs = decl->parameters.has_varargs;
68 69 70
  Builtin::Kind kind = !javascript ? Builtin::kStub
                                   : varargs ? Builtin::kVarArgsJavaScript
                                             : Builtin::kFixedArgsJavaScript;
71

72
  if (varargs && !javascript) {
73 74
    Error("Rest parameters require ", decl->name,
          " to be a JavaScript builtin");
75
  }
76

77 78 79 80 81 82 83 84
  if (javascript) {
    if (!signature.return_type->IsSubtypeOf(TypeOracle::GetJSAnyType())) {
      Error("Return type of JavaScript-linkage builtins has to be JSAny.")
          .Position(decl->return_type->pos);
    }
    for (size_t i = signature.implicit_count;
         i < signature.parameter_types.types.size(); ++i) {
      const Type* parameter_type = signature.parameter_types.types[i];
85 86 87 88
      if (!TypeOracle::GetJSAnyType()->IsSubtypeOf(parameter_type)) {
        Error(
            "Parameters of JavaScript-linkage builtins have to be a supertype "
            "of JSAny.")
89 90 91 92 93
            .Position(decl->parameters.types[i]->pos);
      }
    }
  }

94
  for (size_t i = 0; i < signature.types().size(); ++i) {
95 96 97 98
    if (signature.types()[i]->StructSupertype()) {
      Error("Builtin do not support structs as arguments, but argument ",
            signature.parameter_names[i], " has type ", *signature.types()[i],
            ".");
99 100 101
    }
  }

102 103 104 105 106
  if (signature.return_type->StructSupertype() && javascript) {
    Error(
        "Builtins with JS linkage cannot return structs, but the return type "
        "is ",
        *signature.return_type, ".");
107 108
  }

109 110 111 112
  if (signature.return_type == TypeOracle::GetVoidType()) {
    Error("Builtins cannot have return type void.");
  }

113 114 115 116 117 118
  Builtin* builtin = Declarations::CreateBuiltin(std::move(external_name),
                                                 std::move(readable_name), kind,
                                                 std::move(signature), body);
  // TODO(v8:12261): Recheck this.
  // builtin->SetIdentifierPosition(decl->name->pos);
  return builtin;
119 120 121
}

void DeclarationVisitor::Visit(ExternalBuiltinDeclaration* decl) {
122
  Builtin* builtin =
123
      CreateBuiltin(decl, decl->name->value, decl->name->value,
124 125 126
                    TypeVisitor::MakeSignature(decl), base::nullopt);
  builtin->SetIdentifierPosition(decl->name->pos);
  Declarations::Declare(decl->name->value, builtin);
127 128
}

129 130
void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl) {
  Signature signature = TypeVisitor::MakeSignature(decl);
131 132 133 134 135
  if (signature.parameter_types.types.size() == 0) {
    ReportError(
        "Missing parameters for runtime function, at least the context "
        "parameter is required.");
  }
136 137
  if (!(signature.parameter_types.types[0] == TypeOracle::GetContextType() ||
        signature.parameter_types.types[0] == TypeOracle::GetNoContextType())) {
138 139
    ReportError(
        "first parameter to runtime functions has to be the context and have "
140 141
        "type Context or NoContext, but found type ",
        *signature.parameter_types.types[0]);
142
  }
143
  if (!(signature.return_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType()) ||
144 145 146
        signature.return_type == TypeOracle::GetVoidType() ||
        signature.return_type == TypeOracle::GetNeverType())) {
    ReportError(
147 148
        "runtime functions can only return strong tagged values, but "
        "found type ",
149
        *signature.return_type);
150 151
  }
  for (const Type* parameter_type : signature.parameter_types.types) {
152
    if (!parameter_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType())) {
153
      ReportError(
154
          "runtime functions can only take strong tagged parameters, but "
155 156 157
          "found type ",
          *parameter_type);
    }
158 159
  }

160 161 162 163 164 165 166
  RuntimeFunction* function =
      Declarations::DeclareRuntimeFunction(decl->name->value, signature);
  function->SetIdentifierPosition(decl->name->pos);
  function->SetPosition(decl->pos);
  if (GlobalContext::collect_kythe_data()) {
    KytheData::AddFunctionDefinition(function);
  }
167 168
}

169
void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl) {
170
  Macro* macro = Declarations::DeclareMacro(
171 172
      decl->name->value, true, decl->external_assembler_name,
      TypeVisitor::MakeSignature(decl), base::nullopt, decl->op);
173 174 175 176 177
  macro->SetIdentifierPosition(decl->name->pos);
  macro->SetPosition(decl->pos);
  if (GlobalContext::collect_kythe_data()) {
    KytheData::AddFunctionDefinition(macro);
  }
178 179
}

180
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl) {
181 182 183 184 185
  auto builtin = CreateBuiltin(decl, decl->name->value, decl->name->value,
                               TypeVisitor::MakeSignature(decl), decl->body);
  builtin->SetIdentifierPosition(decl->name->pos);
  builtin->SetPosition(decl->pos);
  Declarations::Declare(decl->name->value, builtin);
186 187
}

188
void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl) {
189
  Macro* macro = Declarations::DeclareMacro(
190 191
      decl->name->value, decl->export_to_csa, base::nullopt,
      TypeVisitor::MakeSignature(decl), decl->body, decl->op);
192
  macro->SetIdentifierPosition(decl->name->pos);
193
  macro->SetPosition(decl->pos);
194 195 196
  if (GlobalContext::collect_kythe_data()) {
    KytheData::AddFunctionDefinition(macro);
  }
197 198
}

199 200 201
void DeclarationVisitor::Visit(IntrinsicDeclaration* decl) {
  Declarations::DeclareIntrinsic(decl->name->value,
                                 TypeVisitor::MakeSignature(decl));
202 203
}

204
void DeclarationVisitor::Visit(ConstDeclaration* decl) {
205
  auto constant = Declarations::DeclareNamespaceConstant(
206
      decl->name, TypeVisitor::ComputeType(decl->type), decl->expression);
207 208 209
  if (GlobalContext::collect_kythe_data()) {
    KytheData::AddConstantDefinition(constant);
  }
210 211
}

212
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
213
  std::vector<GenericCallable*> generic_list =
214
      Declarations::LookupGeneric(decl->name->value);
215 216
  // Find the matching generic specialization based on the concrete parameter
  // list.
217
  GenericCallable* matching_generic = nullptr;
218
  Signature signature_with_types = TypeVisitor::MakeSignature(decl);
219
  for (GenericCallable* generic : generic_list) {
220 221 222
    // This argument inference is just to trigger constraint checking on the
    // generic arguments.
    TypeArgumentInference inference = generic->InferSpecializationTypes(
223 224 225 226
        TypeVisitor::ComputeTypeVector(decl->generic_parameters), {});
    if (inference.HasFailed()) {
      continue;
    }
227
    Signature generic_signature_with_types =
228
        MakeSpecializedSignature(SpecializationKey<GenericCallable>{
229
            generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
230 231
    if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
                                            ParameterMode::kIgnoreImplicit)) {
232
      if (matching_generic != nullptr) {
233
        std::stringstream stream;
234
        stream << "specialization of " << decl->name
235
               << " is ambigous, it matches more than one generic declaration ("
236
               << *matching_generic << " and " << *generic << ")";
237 238
        ReportError(stream.str());
      }
239
      matching_generic = generic;
240
    }
241
  }
242

243
  if (matching_generic == nullptr) {
244
    std::stringstream stream;
245
    if (generic_list.size() == 0) {
246 247 248
      stream << "no generic defined with the name " << decl->name;
      ReportError(stream.str());
    }
249
    stream << "specialization of " << decl->name
250 251 252 253
           << " doesn't match any generic declaration\n";
    stream << "specialization signature:";
    stream << "\n  " << signature_with_types;
    stream << "\ncandidates are:";
254
    for (GenericCallable* generic : generic_list) {
255
      stream << "\n  "
256
             << MakeSpecializedSignature(SpecializationKey<GenericCallable>{
257 258
                    generic,
                    TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
259
    }
260 261 262
    ReportError(stream.str());
  }

263 264 265 266 267
  if (GlobalContext::collect_language_server_data()) {
    LanguageServerData::AddDefinition(decl->name->pos,
                                      matching_generic->IdentifierPosition());
  }

268 269
  CallableDeclaration* generic_declaration = matching_generic->declaration();

270 271 272
  Specialize(SpecializationKey<GenericCallable>{matching_generic,
                                                TypeVisitor::ComputeTypeVector(
                                                    decl->generic_parameters)},
273
             generic_declaration, decl, decl->body, decl->pos);
274 275
}

276
void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
277
  const Type* type = TypeVisitor::ComputeType(decl->type);
278 279 280 281 282 283 284
  if (!type->IsConstexpr()) {
    std::stringstream stream;
    stream << "extern constants must have constexpr type, but found: \""
           << *type << "\"\n";
    ReportError(stream.str());
  }

285 286 287 288 289
  ExternConstant* constant =
      Declarations::DeclareExternConstant(decl->name, type, decl->literal);
  if (GlobalContext::collect_kythe_data()) {
    KytheData::AddConstantDefinition(constant);
  }
290 291
}

292 293 294 295
void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
  GlobalContext::AddCppInclude(decl->include_path);
}

296
void DeclarationVisitor::DeclareSpecializedTypes(
297
    const SpecializationKey<GenericCallable>& key) {
298
  size_t i = 0;
299
  const std::size_t generic_parameter_count =
300
      key.generic->generic_parameters().size();
301
  if (generic_parameter_count != key.specialized_types.size()) {
302 303
    std::stringstream stream;
    stream << "Wrong generic argument count for specialization of \""
304 305
           << key.generic->name() << "\", expected: " << generic_parameter_count
           << ", actual: " << key.specialized_types.size();
306 307 308
    ReportError(stream.str());
  }

309
  for (auto type : key.specialized_types) {
310
    Identifier* generic_type_name = key.generic->generic_parameters()[i++].name;
311 312
    TypeAlias* alias = Declarations::DeclareType(generic_type_name, type);
    alias->SetIsUserDefined(false);
313 314 315
  }
}

316
Signature DeclarationVisitor::MakeSpecializedSignature(
317
    const SpecializationKey<GenericCallable>& key) {
318
  CurrentScope::Scope generic_scope(key.generic->ParentScope());
319
  // Create a temporary fake-namespace just to temporarily declare the
320
  // specialization aliases for the generic types to create a signature.
321 322
  Namespace tmp_namespace("_tmp");
  CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
323
  DeclareSpecializedTypes(key);
324
  return TypeVisitor::MakeSignature(key.generic->declaration());
325
}
326

327
Callable* DeclarationVisitor::SpecializeImplicit(
328
    const SpecializationKey<GenericCallable>& key) {
329 330 331
  base::Optional<Statement*> body = key.generic->CallableBody();
  if (!body && IntrinsicDeclaration::DynamicCast(key.generic->declaration()) ==
                   nullptr) {
332 333
    ReportError("missing specialization of ", key.generic->name(),
                " with types <", key.specialized_types, "> declared at ",
334
                key.generic->Position());
335
  }
336 337
  SpecializationRequester requester{CurrentSourcePosition::Get(),
                                    CurrentScope::Get(), ""};
338
  CurrentScope::Scope generic_scope(key.generic->ParentScope());
339 340
  Callable* result = Specialize(key, key.generic->declaration(), base::nullopt,
                                body, CurrentSourcePosition::Get());
341
  result->SetIsUserDefined(false);
342 343
  requester.name = result->ReadableName();
  result->SetSpecializationRequester(requester);
344 345 346 347 348 349
  CurrentScope::Scope callable_scope(result);
  DeclareSpecializedTypes(key);
  return result;
}

Callable* DeclarationVisitor::Specialize(
350 351
    const SpecializationKey<GenericCallable>& key,
    CallableDeclaration* declaration,
352
    base::Optional<const SpecializationDeclaration*> explicit_specialization,
353 354
    base::Optional<Statement*> body, SourcePosition position) {
  CurrentSourcePosition::Scope pos_scope(position);
355
  size_t generic_parameter_count = key.generic->generic_parameters().size();
356
  if (generic_parameter_count != key.specialized_types.size()) {
357 358
    std::stringstream stream;
    stream << "number of template parameters ("
359 360
           << std::to_string(key.specialized_types.size())
           << ") to intantiation of generic " << declaration->name
361
           << " doesnt match the generic's declaration ("
362
           << std::to_string(generic_parameter_count) << ")";
363 364
    ReportError(stream.str());
  }
365
  if (key.generic->GetSpecialization(key.specialized_types)) {
366 367
    ReportError("cannot redeclare specialization of ", key.generic->name(),
                " with types <", key.specialized_types, ">");
368 369
  }

370 371 372 373
  Signature type_signature =
      explicit_specialization
          ? TypeVisitor::MakeSignature(*explicit_specialization)
          : MakeSpecializedSignature(key);
374 375

  std::string generated_name = Declarations::GetGeneratedCallableName(
376
      declaration->name->value, key.specialized_types);
377
  std::stringstream readable_name;
378
  readable_name << declaration->name->value << "<";
379 380 381 382 383 384 385
  bool first = true;
  for (const Type* t : key.specialized_types) {
    if (!first) readable_name << ", ";
    readable_name << *t;
    first = false;
  }
  readable_name << ">";
386 387
  Callable* callable;
  if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
388 389 390
    callable =
        Declarations::CreateTorqueMacro(generated_name, readable_name.str(),
                                        false, type_signature, *body, true);
391
  } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
392 393
    callable =
        Declarations::CreateIntrinsic(declaration->name->value, type_signature);
394 395
  } else {
    BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
396 397 398
    callable =
        CreateBuiltin(builtin, GlobalContext::MakeUniqueName(generated_name),
                      readable_name.str(), type_signature, *body);
399
  }
400
  key.generic->AddSpecialization(key.specialized_types, callable);
401
  return callable;
402 403
}

404
void PredeclarationVisitor::ResolvePredeclarations() {
405 406 407 408
  const auto& all_declarables = GlobalContext::AllDeclarables();
  for (size_t i = 0; i < all_declarables.size(); ++i) {
    Declarable* declarable = all_declarables[i].get();
    if (const TypeAlias* alias = TypeAlias::DynamicCast(declarable)) {
409 410 411
      CurrentScope::Scope scope_activator(alias->ParentScope());
      CurrentSourcePosition::Scope position_activator(alias->Position());
      alias->Resolve();
412
    }
413 414 415
  }
}

416 417 418
}  // namespace torque
}  // namespace internal
}  // namespace v8