Beispiel #1
0
// Returns true if we found enough information to terminate optimization.
static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op)
{
    if (JSActivation* activation = jsDynamicCast<JSActivation*>(scope)) {
        if (ident == exec->propertyNames().arguments) {
            // We know the property will be at this activation scope, but we don't know how to cache it.
            op = ResolveOp(Dynamic, 0, 0, 0, 0);
            return true;
        }

        SymbolTableEntry entry = activation->symbolTable()->get(ident.impl());
        if (entry.isReadOnly() && getOrPut == Put) {
            // We know the property will be at this activation scope, but we don't know how to cache it.
            op = ResolveOp(Dynamic, 0, 0, 0, 0);
            return true;
        }

        if (!entry.isNull()) {
            op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, activation->structure(), 0, entry.getIndex());
            return true;
        }

        if (activation->symbolTable()->usesNonStrictEval())
            needsVarInjectionChecks = true;
        return false;
    }

    if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(scope)) {
        SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl());
        if (!entry.isNull()) {
            if (getOrPut == Put && entry.isReadOnly()) {
                // We know the property will be at global scope, but we don't know how to cache it.
                op = ResolveOp(Dynamic, 0, 0, 0, 0);
                return true;
            }

            op = ResolveOp(
                makeType(GlobalVar, needsVarInjectionChecks), depth, 0, entry.watchpointSet(),
                reinterpret_cast<uintptr_t>(globalObject->registerAt(entry.getIndex()).slot()));
            return true;
        }

        PropertySlot slot(globalObject);
        if (!globalObject->getOwnPropertySlot(globalObject, exec, ident, slot)
            || !slot.isCacheableValue()
            || !globalObject->structure()->propertyAccessesAreCacheable()
            || (globalObject->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut == Put)) {
            // We know the property will be at global scope, but we don't know how to cache it.
            ASSERT(!scope->next());
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0);
            return true;
        }

        op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, slot.cachedOffset());
        return true;
    }

    op = ResolveOp(Dynamic, 0, 0, 0, 0);
    return true;
}
Beispiel #2
0
Type Type::substitute(const std::vector<Type>& types,
                      const std::vector<Type>& replacements) const {
  NodeManagerScope nms(d_nodeManager);

  vector<TypeNode> typesNodes, replacementsNodes;

  for(vector<Type>::const_iterator i = types.begin(),
        iend = types.end();
      i != iend;
      ++i) {
    typesNodes.push_back(*(*i).d_typeNode);
  }

  for(vector<Type>::const_iterator i = replacements.begin(),
        iend = replacements.end();
      i != iend;
      ++i) {
    replacementsNodes.push_back(*(*i).d_typeNode);
  }

  return makeType(d_typeNode->substitute(typesNodes.begin(),
                                         typesNodes.end(),
                                         replacementsNodes.begin(),
                                         replacementsNodes.end()));
}
Beispiel #3
0
    /**
     * @brief ComponentsMaker::makeField
     * @return
     */
    OptionalEntity ComponentsMaker::makeField(const Tokens &tokens)
    {
        Q_ASSERT(!tokens.isEmpty() && tokens[int(FieldGroupNames::Typename)]->isSingle() &&
                 !tokens[int(FieldGroupNames::Typename)]->token().isEmpty() &&
                 tokens[int(FieldGroupNames::Name)]->isSingle() &&
                 !tokens[int(FieldGroupNames::Name)]->token().isEmpty());

        Q_ASSERT(checkCommonState());

        // Make field with lhs keywords
        auto newField = std::make_shared<entity::Field>();
        newField->setName(tokens[int(FieldGroupNames::Name)]->token());
        if (!tokens[int(FieldGroupNames::LhsKeywords)]->token().isEmpty()) {
            auto keyword =
                utility::fieldKeywordFromString(tokens[int(FieldGroupNames::LhsKeywords)]->token());
            Q_ASSERT(keyword != entity::FieldKeyword::Invalid);
            newField->addKeyword(keyword);
        }

        // Make type
        Tokens typeTokens(int(TypeGroups::GroupsCount));
        std::copy(std::begin(tokens) + int(FieldGroupNames::ConstStatus),
                  std::begin(tokens) + int(FieldGroupNames::Name),        // do not include name
                  std::begin(typeTokens) + int(TypeGroups::ConstStatus)); // add first group offset
        auto optionalType = makeType(typeTokens);
        if (!optionalType.errorMessage.isEmpty())
            return {optionalType.errorMessage, nullptr};

        Q_ASSERT(optionalType.resultEntity);
        newField->setTypeId(optionalType.resultEntity->id());

        return {"", newField};
    }
Beispiel #4
0
SortType SortConstructorType::instantiate(const std::vector<Type>& params) const {
  NodeManagerScope nms(d_nodeManager);
  vector<TypeNode> paramsNodes;
  for(vector<Type>::const_iterator i = params.begin(),
        iend = params.end();
      i != iend;
      ++i) {
    paramsNodes.push_back(*getTypeNode(*i));
  }
  return SortType(makeType(d_nodeManager->mkSort(*d_typeNode, paramsNodes)));
}
Beispiel #5
0
vector<Type> SExprType::getTypes() const {
  NodeManagerScope nms(d_nodeManager);
  vector<Type> types;
  vector<TypeNode> typeNodes = d_typeNode->getSExprTypes();
  vector<TypeNode>::iterator it = typeNodes.begin();
  vector<TypeNode>::iterator it_end = typeNodes.end();
  for(; it != it_end; ++ it) {
    types.push_back(makeType(*it));
  }
  return types;
}
Beispiel #6
0
std::vector<Type> DatatypeType::getParamTypes() const {
  NodeManagerScope nms(d_nodeManager);
  vector<Type> params;
  vector<TypeNode> paramNodes = d_typeNode->getParamTypes();
  vector<TypeNode>::iterator it = paramNodes.begin();
  vector<TypeNode>::iterator it_end = paramNodes.end();
  for(; it != it_end; ++it) {
    params.push_back(makeType(*it));
  }
  return params;
}
Beispiel #7
0
std::vector<Type> ConstructorType::getArgTypes() const {
  NodeManagerScope nms(d_nodeManager);
  vector<Type> args;
  vector<TypeNode> argNodes = d_typeNode->getArgTypes();
  vector<TypeNode>::iterator it = argNodes.begin();
  vector<TypeNode>::iterator it_end = argNodes.end();
  for(; it != it_end; ++ it) {
    args.push_back(makeType(*it));
  }
  return args;
}
Beispiel #8
0
    /**
     * @brief SignatureMaker::makeTypeOrExt
     * @param type
     * @return
     */
    QString SignatureMaker::makeTypeOrExtType(const Entity::SharedType &type) const
    {
        if (!type)
            return "";

        if (type->hashType() == Entity::ExtendedType::staticHashType())
            // Return extended type which may be alias (with optioanl *, &, const)
            return makeExtType(std::static_pointer_cast<Entity::ExtendedType>(type));
        else
            // Or return name (with namespaces) of type, class, enum or union
            return makeType(type);
    }
Beispiel #9
0
DatatypeType DatatypeType::instantiate(const std::vector<Type>& params) const {
  NodeManagerScope nms(d_nodeManager);
  TypeNode cons = d_nodeManager->mkTypeConst( getDatatype() );
  vector<TypeNode> paramsNodes;
  paramsNodes.push_back( cons );
  for(vector<Type>::const_iterator i = params.begin(),
        iend = params.end();
      i != iend;
      ++i) {
    paramsNodes.push_back(*getTypeNode(*i));
  }
  return DatatypeType(makeType(d_nodeManager->mkTypeNode(kind::PARAMETRIC_DATATYPE, paramsNodes)));
}
Beispiel #10
0
std::shared_ptr<TypeInfo> DwarfVariableFinder::getType(const DWARFDie &die) {

  if (!die.isValid()) {
    assert(0);
    return std::make_shared<TypeInfo>("", ~0u);
  }

  auto die_offset = die.getOffset();  
  if(typeDict.count(die_offset)) {
    return typeDict[die_offset];
  }

  auto result = makeType(die);
  typeDict[die_offset] = result;
  return result;
}
Beispiel #11
0
Type ArrayType::getIndexType() const {
  return makeType(d_typeNode->getArrayIndexType());
}
Beispiel #12
0
DatatypeType ConstructorType::getRangeType() const {
  return DatatypeType(makeType(d_typeNode->getConstructorRangeType()));
}
Beispiel #13
0
    /**
     * @brief ComponentsMaker::makeMethod
     * @param tokens
     * @return
     */
    OptionalEntity ComponentsMaker::makeMethod(const Tokens &tokens)
    {
        Q_ASSERT(!tokens.isEmpty() &&
                 tokens[int(MethodsGroupsNames::ReturnType)]->isMulti() &&
                 tokens[int(MethodsGroupsNames::Name)]->isSingle());

        Q_ASSERT(checkCommonState());

        entity::SharedMethod newMethod = std::make_shared<entity::ClassMethod>();

        // Add Lhs
        auto lhsToken = tokens[int(MethodsGroupsNames::LhsKeywords)];
        Q_ASSERT(!lhsToken->isEmpty() && lhsToken->isSingle());
        for (auto &&w : lhsToken->token().split(QChar::Space, QString::SkipEmptyParts)) {
            entity::LhsIdentificator id = utility::methodLhsIdFromString(w);
            Q_ASSERT(id != entity::LhsIdentificator::None);
            newMethod->addLhsIdentificator(id);
        }


        // Add return type
        auto returnTypeToken = tokens[int(MethodsGroupsNames::ReturnType)];
        Q_ASSERT(returnTypeToken->isMulti() && !returnTypeToken->isEmpty());
        auto returnType = makeType(returnTypeToken->tokens());

        if (!returnType.errorMessage.isEmpty())
            return {returnType.errorMessage, nullptr};

        newMethod->setReturnTypeId(returnType.resultEntity->id());

        // Add name
        newMethod->setName(tokens[int(MethodsGroupsNames::Name)]->token());

        // Add arguments
        auto argumentsToken = tokens[int(MethodsGroupsNames::Arguments)];
        Q_ASSERT(argumentsToken->isEmpty() || argumentsToken->isMulti());
        if (argumentsToken->isMulti()) {
            auto argumentsTokens = argumentsToken->tokens();
            for (auto &&argumentToken : argumentsTokens) {
                Q_ASSERT(argumentToken->isMulti());

                auto argSubTokens = argumentToken->tokens();
                Q_ASSERT(argSubTokens.size() == int(Argument::GroupsCount));

                Q_ASSERT(argSubTokens[int(Argument::Name)]->isSingle());
                auto name = argSubTokens[int(Argument::Name)]->token();

                Q_ASSERT(argSubTokens[int(Argument::Type)]->isMulti());
                auto type = makeType(argSubTokens[int(Argument::Type)]->tokens());
                if (!type.errorMessage.isEmpty())
                    return {tr("Wrong type of argument: %1. Error: %2.").arg(
                                QString::number(argumentsTokens.indexOf(argumentToken)),
                                type.errorMessage
                            ), nullptr};

                Q_ASSERT(type.resultEntity);
                newMethod->addParameter(name, type.resultEntity->id());
            }
        }

        // Const
        auto constArgument = tokens[int(MethodsGroupsNames::Const)];
        Q_ASSERT(!constArgument->isEmpty() && constArgument->isSingle());

        const QString &token = constArgument->token();
        if (!token.isEmpty()) {
            if (token == "const")
                newMethod->setConstStatus(true);
            else
                return {tr("Wrong const status token: %1.").arg(constArgument->token()), nullptr};
        }

        // Rhs
        auto rhsArgument = tokens[int(MethodsGroupsNames::RhsKeywords)];
        Q_ASSERT(!rhsArgument->isEmpty() && rhsArgument->isSingle());

        const QString &rhsToken = rhsArgument->token();
        if (!rhsToken.isEmpty()) {
            entity::RhsIdentificator rhsId = utility::methodRhsIdFromString(rhsToken);
            if (rhsId != entity::RhsIdentificator::None)
                newMethod->setRhsIdentificator(rhsId);
            else
                return {tr("Wrong rhs keyword: %1").arg(rhsToken), nullptr};
        }

        return {"", newMethod};
    }
Beispiel #14
0
// Returns true if we found enough information to terminate optimization.
static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op, InitializationMode initializationMode)
{
    if (scope->isJSLexicalEnvironment()) {
        JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(scope);
        if (ident == exec->propertyNames().arguments) {
            // We know the property will be at this lexical environment scope, but we don't know how to cache it.
            op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
            return true;
        }

        SymbolTable* symbolTable = lexicalEnvironment->symbolTable();
        {
            ConcurrentJSLocker locker(symbolTable->m_lock);
            auto iter = symbolTable->find(locker, ident.impl());
            if (iter != symbolTable->end(locker)) {
                SymbolTableEntry& entry = iter->value;
                ASSERT(!entry.isNull());
                if (entry.isReadOnly() && getOrPut == Put) {
                    // We know the property will be at this lexical environment scope, but we don't know how to cache it.
                    op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
                    return true;
                }

                op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, lexicalEnvironment, entry.watchpointSet(), entry.scopeOffset().offset());
                return true;
            }
        }

        if (scope->type() == ModuleEnvironmentType) {
            JSModuleEnvironment* moduleEnvironment = jsCast<JSModuleEnvironment*>(scope);
            AbstractModuleRecord* moduleRecord = moduleEnvironment->moduleRecord();
            AbstractModuleRecord::Resolution resolution = moduleRecord->resolveImport(exec, ident);
            if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) {
                AbstractModuleRecord* importedRecord = resolution.moduleRecord;
                JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironment();
                SymbolTable* symbolTable = importedEnvironment->symbolTable();
                ConcurrentJSLocker locker(symbolTable->m_lock);
                auto iter = symbolTable->find(locker, resolution.localName.impl());
                ASSERT(iter != symbolTable->end(locker));
                SymbolTableEntry& entry = iter->value;
                ASSERT(!entry.isNull());
                op = ResolveOp(makeType(ModuleVar, needsVarInjectionChecks), depth, 0, importedEnvironment, entry.watchpointSet(), entry.scopeOffset().offset(), resolution.localName.impl());
                return true;
            }
        }

        if (symbolTable->usesNonStrictEval())
            needsVarInjectionChecks = true;
        return false;
    }

    if (scope->isGlobalLexicalEnvironment()) {
        JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(scope);
        SymbolTable* symbolTable = globalLexicalEnvironment->symbolTable();
        ConcurrentJSLocker locker(symbolTable->m_lock);
        auto iter = symbolTable->find(locker, ident.impl());
        if (iter != symbolTable->end(locker)) {
            SymbolTableEntry& entry = iter->value;
            ASSERT(!entry.isNull());
            if (getOrPut == Put && entry.isReadOnly() && !isInitialization(initializationMode)) {
                // We know the property will be at global lexical environment, but we don't know how to cache it.
                op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
                return true;
            }

            // We can force const Initialization to always go down the fast path. It is provably impossible to construct
            // a program that needs a var injection check here. You can convince yourself of this as follows:
            // Any other let/const/class would be a duplicate of this in the global scope, so we would never get here in that situation.
            // Also, if we had an eval in the global scope that defined a const, it would also be a duplicate of this const, and so it would
            // also throw an error. Therefore, we're *the only* thing that can assign to this "const" slot for the first (and only) time. Also, 
            // we will never have a Dynamic ResolveType here because if we were inside a "with" statement, that would mean the "const" definition 
            // isn't a global, it would be a local to the "with" block. 
            // We still need to make the slow path correct for when we need to fire a watchpoint.
            ResolveType resolveType = initializationMode == InitializationMode::ConstInitialization ? GlobalLexicalVar : makeType(GlobalLexicalVar, needsVarInjectionChecks);
            op = ResolveOp(
                resolveType, depth, 0, 0, entry.watchpointSet(),
                reinterpret_cast<uintptr_t>(globalLexicalEnvironment->variableAt(entry.scopeOffset()).slot()));
            return true;
        }

        return false;
    }

    if (scope->isGlobalObject()) {
        JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(scope);
        {
            SymbolTable* symbolTable = globalObject->symbolTable();
            ConcurrentJSLocker locker(symbolTable->m_lock);
            auto iter = symbolTable->find(locker, ident.impl());
            if (iter != symbolTable->end(locker)) {
                SymbolTableEntry& entry = iter->value;
                ASSERT(!entry.isNull());
                if (getOrPut == Put && entry.isReadOnly()) {
                    // We know the property will be at global scope, but we don't know how to cache it.
                    op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
                    return true;
                }

                op = ResolveOp(
                    makeType(GlobalVar, needsVarInjectionChecks), depth, 0, 0, entry.watchpointSet(),
                    reinterpret_cast<uintptr_t>(globalObject->variableAt(entry.scopeOffset()).slot()));
                return true;
            }
        }

        PropertySlot slot(globalObject, PropertySlot::InternalMethodType::VMInquiry);
        bool hasOwnProperty = globalObject->getOwnPropertySlot(globalObject, exec, ident, slot);
        if (!hasOwnProperty) {
            op = ResolveOp(makeType(UnresolvedProperty, needsVarInjectionChecks), 0, 0, 0, 0, 0);
            return true;
        }

        if (!slot.isCacheableValue()
            || !globalObject->structure()->propertyAccessesAreCacheable()
            || (globalObject->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut == Put)) {
            // We know the property will be at global scope, but we don't know how to cache it.
            ASSERT(!scope->next());
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), 0, 0, 0, 0, 0);
            return true;
        }

        
        WatchpointState state = globalObject->structure()->ensurePropertyReplacementWatchpointSet(exec->vm(), slot.cachedOffset())->state();
        if (state == IsWatched && getOrPut == Put) {
            // The field exists, but because the replacement watchpoint is still intact. This is
            // kind of dangerous. We have two options:
            // 1) Invalidate the watchpoint set. That would work, but it's possible that this code
            //    path never executes - in which case this would be unwise.
            // 2) Have the invalidation happen at run-time. All we have to do is leave the code
            //    uncached. The only downside is slightly more work when this does execute.
            // We go with option (2) here because it seems less evil.
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0, 0);
        } else
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset());
        return true;
    }

    op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
    return true;
}
Beispiel #15
0
// Returns true if we found enough information to terminate optimization.
static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op)
{
    if (JSActivation* activation = jsDynamicCast<JSActivation*>(scope)) {
        if (ident == exec->propertyNames().arguments) {
            // We know the property will be at this activation scope, but we don't know how to cache it.
            op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
            return true;
        }

        SymbolTableEntry entry = activation->symbolTable()->get(ident.impl());
        if (entry.isReadOnly() && getOrPut == Put) {
            // We know the property will be at this activation scope, but we don't know how to cache it.
            op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
            return true;
        }

        if (!entry.isNull()) {
            op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, activation, entry.watchpointSet(), entry.getIndex());
            return true;
        }

        if (activation->symbolTable()->usesNonStrictEval())
            needsVarInjectionChecks = true;
        return false;
    }

    if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(scope)) {
        SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl());
        if (!entry.isNull()) {
            if (getOrPut == Put && entry.isReadOnly()) {
                // We know the property will be at global scope, but we don't know how to cache it.
                op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
                return true;
            }

            op = ResolveOp(
                makeType(GlobalVar, needsVarInjectionChecks), depth, 0, 0, entry.watchpointSet(),
                reinterpret_cast<uintptr_t>(globalObject->registerAt(entry.getIndex()).slot()));
            return true;
        }

        PropertySlot slot(globalObject);
        if (!globalObject->getOwnPropertySlot(globalObject, exec, ident, slot)
            || !slot.isCacheableValue()
            || !globalObject->structure()->propertyAccessesAreCacheable()
            || (globalObject->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut == Put)) {
            // We know the property will be at global scope, but we don't know how to cache it.
            ASSERT(!scope->next());
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0, 0);
            return true;
        }
        
        WatchpointState state = globalObject->structure()->ensurePropertyReplacementWatchpointSet(exec->vm(), slot.cachedOffset())->state();
        if (state == IsWatched && getOrPut == Put) {
            // The field exists, but because the replacement watchpoint is still intact. This is
            // kind of dangerous. We have two options:
            // 1) Invalidate the watchpoint set. That would work, but it's possible that this code
            //    path never executes - in which case this would be unwise.
            // 2) Have the invalidation happen at run-time. All we have to do is leave the code
            //    uncached. The only downside is slightly more work when this does execute.
            // We go with option (2) here because it seems less evil.
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0, 0);
        } else
            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset());
        return true;
    }

    op = ResolveOp(Dynamic, 0, 0, 0, 0, 0);
    return true;
}
Beispiel #16
0
Type ArrayType::getConstituentType() const {
  return makeType(d_typeNode->getArrayConstituentType());
}
Beispiel #17
0
Type SetType::getElementType() const {
  return makeType(d_typeNode->getSetElementType());
}
Beispiel #18
0
std::shared_ptr<TypeInfo> DwarfVariableFinder::makeType(const DWARFDie &die) {

  if (!die.isValid()) {
    return std::make_shared<TypeInfo>("", ~0u);
  }
  auto opSize = die.find(dwarf::DW_AT_byte_size);
  unsigned size = 1;
  if(opSize.hasValue()) {
    size = opSize.getValue().getAsUnsignedConstant().getValue();  
  }

  std::string type_encoding = "";
  raw_string_ostream SS(type_encoding);

  switch (die.getTag()) {
    case dwarf::DW_TAG_base_type: {  
                                    auto opForm = die.find(dwarf::DW_AT_encoding);
                                    auto opEnc = opForm->getAsUnsignedConstant();
                                    assert(opEnc < HANDLE_DW_ATE_SIZE);
                                    SS << HANDLE_DW_ATE[*opEnc];
                                    opForm = die.find(dwarf::DW_AT_name);
                                    opForm->dump(SS);
                                    return std::make_shared<TypeInfo>(SS.str(), size);
                                  }
    case dwarf::DW_TAG_reference_type:
    case dwarf::DW_TAG_rvalue_reference_type:
    case dwarf::DW_TAG_pointer_type: {
                                       auto baseType = getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type));
                                       SS <<  "*" << baseType->getName();
                                       return std::make_shared<TypeInfo>(SS.str(), size);
                                     }
    case dwarf::DW_TAG_array_type: {
                                     auto baseType = getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type));
                                     SS << baseType->getName();
                                     size *= baseType->getSize();

                                     for (auto childDie = die.getFirstChild(); childDie && childDie.getTag(); 
                                         childDie = childDie.getSibling()) {
                                       std::shared_ptr<TypeInfo> rangeInfo = makeType(childDie);
                                       SS << "[";
                                       SS <<  rangeInfo->getName();
                                       SS << "]";
                                       size *= rangeInfo->getSize();
                                     }
                                     return std::make_shared<TypeInfo>(SS.str(), size);
                                   }
    case dwarf::DW_TAG_subrange_type: {
                                        uint64_t count = 0;
                                        auto opCount = die.find(dwarf::DW_AT_count);
                                        if(opCount.hasValue()) {
                                          count = opCount.getValue().getAsUnsignedConstant().getValue();
                                        } else {
                                          opCount = die.find(dwarf::DW_AT_upper_bound);
                                          assert(opCount.hasValue());
                                          count = opCount.getValue().getAsUnsignedConstant().getValue()  +1;
                                        }
                                        return std::make_shared<TypeInfo>(std::to_string(count), count);
                                      }
    case dwarf::DW_TAG_typedef: {
                                  return getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type));
                                }

    case dwarf::DW_TAG_structure_type:
    case dwarf::DW_TAG_class_type:
    case dwarf::DW_TAG_union_type: {
                                     SS << "struct" << dwarf::toString(die.find(dwarf::DW_AT_name), "None");
                                     auto structType = std::make_shared<TypeInfo>(SS.str(), size);

                                     // Add subentries for various pieces of the struct.
                                     for (auto childDie = die.getFirstChild(); childDie && childDie.getTag(); childDie = childDie.getSibling()) {
                                       if (childDie.getTag() != dwarf::DW_TAG_inheritance &&
                                           childDie.getTag() != dwarf::DW_TAG_member) {
                                         continue;
                                       }
                                       uint64_t dataMemOffset = dwarf::toUnsigned(childDie.find(dwarf::DW_AT_data_member_location), ~0U);
                                       structType->getFields().emplace_back(makeType(childDie), dataMemOffset);
                                     }
                                     return structType;
                                   }

    case dwarf::DW_TAG_inheritance:
    case dwarf::DW_TAG_member: {
                                 return getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type));
                               }        

    default: {
               auto tagString = TagString(die.getTag());
               if (tagString.empty()) {
                 llvm::errs() << format("DW_TAG_Unknown_%x", die.getTag());
               }
               die.dump(llvm::errs(), 10);
               return std::make_shared<TypeInfo>("", ~0u);
             }
  }
}
Beispiel #19
0
Type Type::substitute(const Type& type, const Type& replacement) const {
  NodeManagerScope nms(d_nodeManager);
  return makeType(d_typeNode->substitute(*type.d_typeNode,
                                         *replacement.d_typeNode));
}
Beispiel #20
0
Type FunctionType::getRangeType() const {
  NodeManagerScope nms(d_nodeManager);
  PrettyCheckArgument(isNull() || isFunction(), this);
  return makeType(d_typeNode->getRangeType());
}
Beispiel #21
0
BooleanType TesterType::getRangeType() const {
  return BooleanType(makeType(d_nodeManager->booleanType()));
}
Beispiel #22
0
  bindError("non null pointer type expected",       nonNullTypeErr);
  bindError("non positive inj expression expected", nonPosInjErr);
  bindError("unexpected object",                    objectErr);
  bindError("positive inj expression expected",     posInjErr);
  bindError("out of range",                         rangeErr);
  bindError("cannot report error",                  reportErr);
  bindError("subsumed form",                        subsumedFormErr);
  bindError("too few elements",                     tooFewElemsErr);
  bindError("too many elements",                    tooManyElemsErr);
  bindError("expression has unexpected type",       typeErr);
  bindError("type exe expression expected",         typeExeErr);
  bindError("type mut expression expected",         typeMutErr);
  bindError("type obj expression expected",         typeObjErr);
  bindError("type size too large",                  typeSizeErr);
  bindError("type type obj expression expected",    typeTypeObjErr);
  bindError("version does not match",               versionErr);
  bindError("zero inj expression expected",         zeroInjErr);

//  Make external types. These must be defined here, and not in a prelude file,
//  because Orson code can't get the alignment or size of a C type. The garbage
//  collector must explicitly mark the types to which names are not bound.

  voidExternal  = makeType(void);
  fileExternal  = makeType(FILE);
  labelExternal = makeType(sigjmp_buf);

//  Bind secret names to externals. We can mention these in the prelude.

  bindSecret("File",  makePrefix(typeHook, fileExternal),  fileExternal);
  bindSecret("Label", makePrefix(typeHook, labelExternal), labelExternal); }
Beispiel #23
0
Type SelectorType::getRangeType() const {
  return makeType((*d_typeNode)[1]);
}
Beispiel #24
0
DatatypeType TesterType::getDomain() const {
  return DatatypeType(makeType((*d_typeNode)[0]));
}
Beispiel #25
-1
static bool runStatement(ASTNode* node, MemoryStack* stack, Scope* scope, RuntimeError* error)
{
    switch (node->nodeType)
    {
        case AST_STATEMENT_TYPE_DEFINITION:
        {
            if (getTypeDefinition(scope, node->typeDefinition.identifier, false))
            {
                *error = RuntimeError{
                    RET_TYPE_ALREADY_DEFINED,
                    node->typeDefinition.identifier,
                    node->typeDefinition.lineNumber
                };

                return false;
            }
            else
            {
                TypeDefinition* typeDef = scopePushToList(scope, stack, &scope->types);
                typeDef->identifier = node->typeDefinition.identifier;
                typeDef->members = {};

                ListIterator<ASTNode> iterator = makeIterator(&node->typeDefinition.definitions);

                int currOffsetInBytes = 0;
                while (hasNext(&iterator))
                {
                    ASTNode* node = getNext(&iterator);

                    StructMember* member = scopePushToList(scope, stack, &typeDef->members);
                    member->identifier = node->variableDeclaration.identifier;
                    member->type = makeType(scope, node->variableDeclaration.typeIdentifier);
                    member->offsetInBytes = currOffsetInBytes;

                    currOffsetInBytes += member->type.definition->totalSizeInBytes;
                }

                typeDef->totalSizeInBytes = currOffsetInBytes;
                return true;
            }
        } break;

        case AST_STATEMENT_VARIABLE_DECLARATION:
        {
            if (getVariable(scope, node->variableDeclaration.identifier, false))
            {
                *error = RuntimeError{ RET_VARIABLE_ALREADY_DEFINED, node->variableDeclaration.identifier, node->variableDeclaration.lineNumber };
                return false;
            }
            else
            {
                Variable* var = defineAVariable(
                    node->variableDeclaration.identifier,
                    makeType(scope, node->variableDeclaration.typeIdentifier), stack, scope);

                if (node->variableDeclaration.expression)
                    return runExpression(node->variableDeclaration.expression, stack, scope, error, &var->value);
                else
                    return true; // TODO: set default value
            }
        } break;

        case AST_STATEMENT_FUNCTION_DEFINITION:
        {
            Function func;

            func.type = FT_INTERNAL;
            func.identifier.name = node->functionDefinition.identifier;
            func.identifier.arguments = {};

            bool stillWorking = true;
            if (!node->functionDefinition.returnType)
                func.returnType = Type{ nullptr, 0 };
            else
            {
                func.returnType = makeType(scope, node->functionDefinition.returnType);
                if (!func.returnType.definition)
                {
                    *error = RuntimeError{ RET_UNDEFINED_TYPE, node->functionDefinition.returnType->typeIdentifier.name, node->functionDefinition.lineNumber };
                    stillWorking = false;
                }
            }

            ListIterator<ASTNode> args = makeIterator(&node->functionDefinition.arguments);
            while (stillWorking && hasNext(&args))
            {
                ASTNode* arg = getNext(&args);

                Argument* argument = scopePushToList(scope, stack, &func.identifier.arguments);
                argument->identifier = arg->variableDeclaration.identifier;
                argument->type = makeType(scope, arg->variableDeclaration.typeIdentifier);

                if (!argument->type.definition)
                {
                    *error = RuntimeError{ RET_UNDEFINED_TYPE, arg->variableDeclaration.typeIdentifier->typeIdentifier.name, arg->variableDeclaration.lineNumber };
                    stillWorking = false;
                }
            }

            func.body = node->functionDefinition.body;

            Function* hasFunc = getFunction(scope, func.identifier, false);
            if (hasFunc)
            {
                *error = RuntimeError{ RET_FUNCTION_ALREADY_DEFINED, node->functionDefinition.identifier, node->functionDefinition.lineNumber };
                stillWorking = false;
            }
            else
            {
                *scopePushToList(scope, stack, &scope->functions) = func;
            }

            return stillWorking;
        } break;

        case AST_STATEMENT_IF:
        {
            Scope ifScope = makeScope(scope);
            Value conditionResult = pushValue(&ifScope, stack, Type{ getTypeDefinition(scope, makeSlice("s32")), false });

            bool stillWorking = runExpression(node->ifStatement.condition, stack, scope, error, &conditionResult);

            if (stillWorking)
            {
                if (*(int*)conditionResult.memory != 0)
                {
                    stillWorking = runStatement(node->ifStatement.ifCase, stack, &ifScope, error);
                }
                else if (node->ifStatement.elseCase != nullptr)
                {
                    stillWorking = runStatement(node->ifStatement.elseCase, stack, &ifScope, error);
                }
            }

            scopeFreeMemory(&ifScope, stack);
            return stillWorking;
        } break;

        case AST_STATEMENT_WHILE:
        {
            Scope whileScope = makeScope(scope);
            Value conditionResult = pushValue(&whileScope, stack, Type{ getTypeDefinition(scope, makeSlice("s32")), false });

            bool stillWorking = runExpression(node->whileStatement.condition, stack, scope, error, &conditionResult);
            if (stillWorking)
            {
                while (*(int*)conditionResult.memory != 0)
                {
                    if (!(stillWorking = runStatement(node->whileStatement.body, stack, &whileScope, error))) break;
                    if (!(stillWorking = runExpression(node->whileStatement.condition, stack, scope, error, &conditionResult))) break;
                }
            }

            scopeFreeMemory(&whileScope, stack);
            return stillWorking;
        } break;

        case AST_STATEMENT_ASSIGNMENT:
        {
            Value value; 
            if (getValue(scope, node->assignment.lValue, error, &value))
            {
                return runExpression(node->assignment.expression, stack, scope, error, &value);
            }
            else
                return false;
        } break;

        case AST_STATEMENTS_BLOCK:
        {
            Scope blockScope = makeScope(scope);
            bool result = runStatements(&node->statementsBlock.statements, stack, &blockScope, error);
            scopeFreeMemory(&blockScope, stack);

            return result;
        } break;

        case AST_FUNCTION_CALL:
        {
            return runFunctionCall(node, stack, scope, error, nullptr);
        } break;

        default:
        {
            assert(!"this is not a statement!");
            return false;
        } break;
    }
}