Esempio n. 1
0
Type *
TypeResolver::resolveBaseType(TypeSpecifier *spec)
{
  switch (spec->resolver()) {
    case TOK_LABEL:
    case TOK_NAME:
      return resolveNameToType(spec->proxy());

    case TOK_DEFINED:
      return spec->getResolvedBase();

    case TOK_FUNCTION:
    {
      FunctionSignature *sig = spec->signature();
      if (!sig->isResolved())
        resolveTypesInSignature(sig);
      return FunctionType::New(sig);
    }

    default:
      // Other cases should have been handled during name resolution.
      assert(false);
      return nullptr;
  }
}
Esempio n. 2
0
Type *
NameResolver::resolveBase(TypeSpecifier &spec)
{
  switch (spec.resolver()) {
    // These are the most common cases - either a primitive type or a signature
    // containing primitive types. In some cases we could have already resolved
    // the type even earlier, for example, the parser does this for certain =
    // builtin tags.
    case TOK_VOID:
      return cc_.types()->getVoid();
    case TOK_IMPLICIT_INT:
      return cc_.types()->getImplicitInt();
    case TOK_INT:
      return cc_.types()->getPrimitive(PrimitiveType::Int32);
    case TOK_BOOL:
      return cc_.types()->getPrimitive(PrimitiveType::Bool);
    case TOK_CHAR:
      return cc_.types()->getPrimitive(PrimitiveType::Char);
    case TOK_FLOAT:
      return cc_.types()->getPrimitive(PrimitiveType::Float);
    case TOK_DEFINED:
      return spec.getResolvedBase();
    case TOK_FUNCTION:
    {
      FunctionSignature *sig = spec.signature();
      if (!sig->isResolved())
        return nullptr;
      return FunctionType::New(sig);
    }

    case TOK_LABEL:
    case TOK_NAME:
    {
      NameProxy *proxy = spec.proxy();
      Symbol *sym = proxy->sym();
      if (!sym) {
        // This can happen if we use a type before it's been defined. We wait
        // until type resolution to try again.
        return nullptr;
      }

      TypeSymbol *ts = sym->asType();
      if (!ts) {
        cc_.report(proxy->loc(), rmsg::not_a_type) << sym->name();
        return nullptr;
      }

      // If we resolved a TypeSymbol, we must have allocated a Type object
      // (even if it's incomplete).
      assert(ts->type());
      return ts->type();
    }

    default:
      return nullptr;
  }
}
Esempio n. 3
0
FunctionCall FunctionCall::deserialize(const Message& message) {
  FunctionSignature signature = FunctionSignature::deserialize(message);

  // Count trailing null bytes
  size_t bytesRead = sizeof(int) * (signature.numArgs() + 1);
  bytesRead += signature.name.size() + 1;

  std::string msgCopy = message.message;
  msgCopy.erase(0, bytesRead);

  return FunctionCall(std::move(signature), msgCopy);
}
Esempio n. 4
0
FunctionSignature *
NameResolver::HandleFunctionSignature(const TypeExpr &te,
                                      ParameterList *params,
                                      bool canResolveEagerly)
{
  FunctionSignature *sig = new (pool_) FunctionSignature(te, params);
  if (te.resolved() && canResolveEagerly) {
#if defined(DEBUG)
    for (size_t i = 0; i < params->length(); i++)
      assert(params->at(i)->sym()->type());
#endif
    sig->setResolved();
  }

  return sig;
}
Esempio n. 5
0
bool
sp::AreFunctionTypesEqual(FunctionType *a, FunctionType *b)
{
  FunctionSignature *af = a->signature();
  FunctionSignature *bf = b->signature();
  if (!AreTypesEquivalent(af->returnType().resolved(),
                          bf->returnType().resolved(),
                          Qualifiers::None))
  {
    return false;
  }

  ParameterList *ap = af->parameters();
  ParameterList *bp = bf->parameters();
  if (ap->length() != bp->length())
    return false;

  for (size_t i = 0; i < ap->length(); i++) {
    VarDecl *arga = ap->at(i);
    VarDecl *argb = bp->at(i);
    if (!AreTypesEquivalent(arga->te().resolved(),
                            argb->te().resolved(),
                            Qualifiers::None))
    {
      return false;
    }
  }
  return true;
}
void
SemanticAnalysis::visitCallExpr(CallExpr *node)
{
    // :TODO: we must verify that the callee is an implemented scripted func.
    Expression *callee = visitForRValue(node->callee());
    if (!callee)
        return;
    if (!callee->type()->isFunction()) {
        cc_.report(node->loc(), rmsg::callee_is_not_a_function)
                << callee->type();
        return;
    }
    node->setCallee(callee);

    FunctionSignature *sig = callee->type()->toFunction()->signature();
    checkCall(sig, node->arguments());

    Type *returnType = sig->returnType().resolved();
    node->setOutput(returnType, VK::rvalue);

    // We mark calls as always having side effects.
    node->setHasSideEffects();
}
Esempio n. 7
0
void
NameResolver::OnLeaveFunctionDecl(FunctionStatement *node)
{
  FunctionSignature *sig = node->signature();

  // For compatibility with SP1, we change implicit-int return values to
  // implicit-void when there is no return value, so we can error when the
  // return value is used. We differentiate this from "void" so the following
  // transitional case does not error:
  //
  //   forward void OnThing1();
  //   OnThing1() {}
  TypeExpr &rt = sig->returnType();
  if (((rt.resolved() && rt.resolved()->isImplicitInt()) ||
       (rt.spec() && rt.spec()->resolver() == TOK_IMPLICIT_INT)) &&
      !(node->token() == TOK_FORWARD || node->token() == TOK_NATIVE) &&
      !encountered_return_value_)
  {
    rt.setResolved(cc_.types()->getImplicitVoid());
  }

  if (!sig->isResolved())
    tr_.addPending(node);
}
 foreach (const ArgumentGroup &group, convention()->argumentGroups()) {
     bool groupIsFull = true;
     foreach (const Argument &argument, group.arguments()) {
         bool argumentIsUsed = false;
         foreach (const MemoryLocation &memoryLocation, argument.locations()) {
             if (isRealArgument(memoryLocation)) {
                 signature.addArgument(memoryLocation);
                 argumentIsUsed = true;
             }
         }
         if (!argumentIsUsed) {
             groupIsFull = false;
             break;
         }
     }
     if (groupIsFull) {
         considerStack = true;
     }
 }
Esempio n. 9
0
int Client::connectToServer(const FunctionSignature& signature) const {
  int binderSocket = connectTo(binderHost, binderPort);
  if (binderSocket < 0) {
    return binderSocket;
  }
  Connection binderConnection(binderSocket);

  // Send a request for the server address
  binderConnection.send(Message::Type::ADDRESS, signature.serialize());
  // Read the response for the server address
  Message message;
  if (binderConnection.read(&message) < 0 ||
      message.type != Message::Type::ADDRESS) {
    binderConnection.close();
    return -1;
  }
  binderConnection.close();
  // Okay, now we have the message with the server address
  auto serverAddress = ServerAddress::deserialize(message);
  return connectTo(serverAddress.hostname, serverAddress.port);
}
FunctionSignature GenericDescriptorAnalyzer::getFunctionSignature() const {
    FunctionSignature signature;

    struct Counts {
        std::size_t defs;
        std::size_t uses;

        Counts(): defs(0), uses(0) {}
    };

    /*
     * Estimate the memory locations of arguments.
     */
    boost::unordered_map<MemoryLocation, Counts> argVotes;

    std::size_t callsCount = callAnalyzers_.size();
    std::size_t functionsCount = 0;

    foreach (GenericCallAnalyzer *callAnalyzer, callAnalyzers_) {
        foreach (const MemoryLocation &memoryLocation, callAnalyzer->argumentLocations()) {
            ++argVotes[memoryLocation].defs;
        }
    }
bool FunctionSignature::operator==(const FunctionSignature &other) const
{
    return name() == other.name() &&
           isArityValid(other.maximumArguments()) &&
           isArityValid(other.minimumArguments());
}