Пример #1
0
Type *
FormTypeParse(Units *units, Node *node, bool allow_anon_structs,
              bool allow_bitfields, bool allow_refs, bool allow_retvals)
{
    Context *ctx = units->top()->ctx;

    node = units->top()->mp->parsePotentialMacroCall(node);
    if (!node) {
        return NULL;
    } else if (node->is_token) {
        return parseTypeToken(units, node);
    }

    std::vector<Node *> *lst = node->list;
    Node *name_node = (*lst)[0];

    if (!name_node->is_token) {
        Error *e = new Error(FirstListElementMustBeAtom, name_node);
        ctx->er->addError(e);
        return NULL;
    }

    Token *token = name_node->token;
    if (token->type != TokenType::String) {
        Error *e = new Error(FirstListElementMustBeSymbol, name_node);
        ctx->er->addError(e);
        return NULL;
    }

    std::vector<Node*> lst_tail;
    if (!strcmp(token->str_value.c_str(), "do")) {
        lst_tail.assign(lst->begin() + 1, lst->end());
        lst = &lst_tail;
        if (lst->size() == 1) {
            return FormTypeParse(units, (*lst)[0], allow_anon_structs,
                                 allow_bitfields, allow_refs,
                                 allow_retvals);
        }
    }

    if (lst->size() < 2) {
        Error *e = new Error(InvalidType, node);
        ctx->er->addError(e);
        return NULL;
    }

    Node *fst_node = (*lst)[0];
    Node *snd_node = (*lst)[1];

    /* If list is a two-element list, where the first element is
     * 'ref', then this is a reference type. */
    if (lst->size() == 2
            && fst_node->is_token
            && !(fst_node->token->str_value.compare("ref"))) {
        if (!allow_refs) {
            Error *e = new Error(RefsNotPermittedHere, node);
            ctx->er->addError(e);
            return NULL;
        }
        /* Reference types are only permitted at the 'node level' of
         * the type. */
        Type *reference_type =
            FormTypeParse(units, snd_node, allow_anon_structs,
                          allow_bitfields);

        if (reference_type == NULL) {
            return NULL;
        }
        return ctx->tr->getReferenceType(reference_type);
    }

    /* If list is a two-element list, where the first element is
     * 'rv-ref', then this is an rvalue reference type. */
    if (lst->size() == 2
            && fst_node->is_token
            && !(fst_node->token->str_value.compare("rv-ref"))) {
        if (!allow_refs) {
            Error *e = new Error(RefsNotPermittedHere, node);
            ctx->er->addError(e);
            return NULL;
        }
        /* Reference types are only permitted at the 'node level' of
         * the type. */
        Type *rvalue_reference_type =
            FormTypeParse(units, snd_node, allow_anon_structs,
                          allow_bitfields);

        if (rvalue_reference_type == NULL) {
            return NULL;
        }
        return ctx->tr->getRvalueReferenceType(rvalue_reference_type);
    }

    /* If list is a two-element list, where the first element is
     * 'retval', then this is a retval type. */
    if (lst->size() == 2
            && fst_node->is_token
            && !(fst_node->token->str_value.compare("retval"))) {
        if (!allow_retvals) {
            Error *e = new Error(RetvalsNotPermittedHere, node);
            ctx->er->addError(e);
            return NULL;
        }
        /* Retval types are only permitted at the 'node level' of
         * the type. */
        Type *retval_type =
            FormTypeParse(units, snd_node, allow_anon_structs,
                          allow_bitfields);

        if (retval_type == NULL) {
            return NULL;
        }
        return ctx->tr->getRetvalType(retval_type);
    }

    /* If list is a two-element list, where the first element is
     * 'struct', then this is an anonymous struct.  If
     * allow_anon_structs is enabled, then construct a list that can
     * in turn be used to create that struct, call
     * parseStructDefinition, and then use that new struct name as the
     * value of this element. */
    if (allow_anon_structs
            && lst->size() == 2
            && fst_node->is_token
            && !(fst_node->token->str_value.compare("struct"))) {
        lst->insert((lst->begin() + 1), new Node("extern"));

        char buf[255];
        sprintf(buf, "__as%d", anon_struct_count++);

        int error_count_begin = ctx->er->getErrorTypeCount(ErrorType::Error);
        FormStructParse(units, new Node(lst), buf);
        int error_count_end = ctx->er->getErrorTypeCount(ErrorType::Error);
        if (error_count_begin != error_count_end) {
            return NULL;
        }

        Type *type = FormTypeParse(units, new Node(buf), false, false);
        assert(type && "unable to retrieve anonymous struct type");
        return type;
    }

    /* If list is a three-element list, where the first element is
     * 'bf', then this is a bitfield type.  Only return such a type
     * if allow_bitfields is enabled. */
    if (allow_bitfields
            && lst->size() == 3
            && fst_node->is_token
            && !(fst_node->token->str_value.compare("bf"))) {
        Type *type = FormTypeParse(units, snd_node, false, false);
        if (!type->isIntegerType()) {
            Error *e = new Error(BitfieldMustHaveIntegerType, node);
            ctx->er->addError(e);
            return NULL;
        }
        int size = FormLiteralIntegerParse((*lst)[2], ctx->er);
        if (size == -1) {
            return NULL;
        }
        return ctx->tr->getBitfieldType(type, size);
    }

    if (!strcmp(fst_node->token->str_value.c_str(), "const")) {
        if (lst->size() != 2) {
            Error *e = new Error(IncorrectNumberOfArgs, node,
                                 "const", "1", ((int) lst->size() - 1));
            ctx->er->addError(e);
            return NULL;
        }

        Type *const_type =
            FormTypeParse(units, snd_node, allow_anon_structs,
                          allow_bitfields);

        if (const_type == NULL) {
            return NULL;
        }
        return ctx->tr->getConstType(const_type);
    }

    if (!strcmp(fst_node->token->str_value.c_str(), "array-of")) {
        if (lst->size() != 3) {
            Error *e = new Error(IncorrectNumberOfArgs, node,
                                 "array-of", "2", ((int) lst->size() - 1));
            ctx->er->addError(e);
            return NULL;
        }

        snd_node = units->top()->mp->parsePotentialMacroCall(snd_node);
        int size = FormLiteralIntegerParse(snd_node, ctx->er);
        if (size == -1) {
            return NULL;
        }

        Type *array_type =
            FormTypeParse(units, (*lst)[2], allow_anon_structs,
                          allow_bitfields);

        if (array_type == NULL) {
            return NULL;
        }
        return ctx->tr->getArrayType(array_type, size);
    }

    if (!strcmp(fst_node->token->str_value.c_str(), "p")) {
        if (!ctx->er->assertArgNums("p", node, 1, 1)) {
            return NULL;
        }

        Type *points_to_type =
            FormTypeParse(units, snd_node, allow_anon_structs,
                          allow_bitfields);

        if (points_to_type == NULL) {
            return NULL;
        }
        return ctx->tr->getPointerType(points_to_type);
    }

    if (!strcmp(fst_node->token->str_value.c_str(), "fn")) {
        if (!ctx->er->assertArgNums("fn", node, 2, 2)) {
            return NULL;
        }

        Type *ret_type =
            FormTypeParse(units, snd_node, allow_anon_structs,
                          allow_bitfields, false, true);

        if (ret_type == NULL) {
            return NULL;
        }
        if (ret_type->is_array) {
            Error *e = new Error(ReturnTypesCannotBeArrays, node);
            ctx->er->addError(e);
            return NULL;
        }

        Node *params = (*lst)[2];

        if (!params->is_list) {
            Error *e = new Error(UnexpectedElement, node,
                                 "list", "fn parameters", "symbol");
            ctx->er->addError(e);
            return NULL;
        }

        std::vector<Type *> parameter_types;
        for (std::vector<Node *>::iterator b = params->list->begin(),
                                           e = params->list->end();
                b != e;
                ++b) {
            Variable *var = new Variable();
            var->type = NULL;

            FormParameterParse(units, var, (*b), allow_anon_structs,
                               allow_bitfields, true);
            if (var->type == NULL) {
                delete var;
                return NULL;
            }

            if (var->type->base_type == BaseType::Void) {
                delete var;
                if (params->list->size() != 1) {
                    Error *e = new Error(VoidMustBeTheOnlyParameter,
                                         params);
                    ctx->er->addError(e);
                    return NULL;
                }
                break;
            }

            if (var->type->base_type == BaseType::VarArgs) {
                if ((params->list->end() - b) != 1) {
                    delete var;
                    Error *e = new Error(VarArgsMustBeLastParameter,
                                         params);
                    ctx->er->addError(e);
                    return NULL;
                }
                parameter_types.push_back(var->type);
                break;
            }
;
            if (var->type->is_function) {
                delete var;
                Error *e = new Error(NonPointerFunctionParameter, (*b));
                ctx->er->addError(e);
                return NULL;
            }

            parameter_types.push_back(var->type);
        }

        Type *type = new Type();
        type->is_function = true;
        type->return_type = ret_type;
        type->parameter_types = parameter_types;

        return type;
    }

    Error *e = new Error(InvalidType, node);
    ctx->er->addError(e);

    return NULL;
}
Пример #2
0
bool
FormStructParse(Units *units, Node *top, const char *name)
{
    Context *ctx = units->top()->ctx;

    if (!ctx->er->assertArgNums("struct", top, 1, 3)) {
        return false;
    }

    ++anon_struct_index;

    std::vector<Node *> *lst = top->list;

    int next_index = 1;
    int linkage = FormLinkageStructParse(ctx, (*lst)[next_index]);
    if (!linkage) {
        return false;
    }
    ++next_index;

    bool res = addOpaqueStruct(units, name, top, linkage);
    if (!res) {
        return false;
    }

    /* If the list contains two members (name and linkage), or
     * three members (name, attributes and linkage), the struct
     * is actually opaque, so return now. */

    if ((lst->size() == 2) || ((lst->size() == 3) && (next_index == 3))) {
        return true;
    }

    /* Parse the struct members. */

    Node *members_node = (*lst)[next_index];

    if (!members_node->is_list) {
        Error *e = new Error(IncorrectArgType, members_node,
                             "struct", "a list", "1", "an atom");
        ctx->er->addError(e);
        return false;
    }

    std::vector<Node *> *members = members_node->list;

    std::vector<Variable *> members_internal;
    for (std::vector<Node *>::iterator b = members->begin(),
                                       e = members->end();
            b != e;
            ++b) {
        Variable *var = new Variable();
        var->type = NULL;

        FormParameterParse(units, var, (*b), true, true, false);
        if (!var->type) {
            Error *e = new Error(InvalidType, (*b));
            ctx->er->addError(e);
            delete var;
            return false;
        }

        if (var->type->base_type == BaseType::Void) {
            Error *e = new Error(TypeNotAllowedInStruct, (*b), "void");
            ctx->er->addError(e);
            delete var;
            return false;
        }

        members_internal.push_back(var);
    }

    /* Convert the members to LLVM types and add the struct to the
     * module. */

    std::vector<llvm::Type*> members_llvm;
    for (std::vector<Variable *>::iterator b = members_internal.begin(),
                                           e = members_internal.end();
            b != e;
            ++b) {
        llvm::Type *type = ctx->toLLVMType((*b)->type, NULL, false);
        if (!type) {
            return false;
        }
        members_llvm.push_back(type);
    }

    std::string symbol;
    ctx->ns()->nameToSymbol(name, &symbol);

    /* If the struct does not already exist in context, then there has
     * been some strange error. */
    Struct *st = ctx->getStruct(name);
    if (!st) {
        Error *e = new Error(UnableToParseForm, top);
        ctx->er->addError(e);
        return false;
    }

    /* If it does exist, but is not opaque, then it cannot be
     * redefined. */
    if (!st->is_opaque) {
        Error *e = new Error(RedeclarationOfStruct, top, name);
        ctx->er->addError(e);
        return false;
    }

    /* Get the struct's type, cast it to a  StructType, and add the
     * members. */
    llvm::StructType *opaque_struct_type =
        llvm::cast<llvm::StructType>(st->type);
    opaque_struct_type->setBody(llvm::ArrayRef<llvm::Type*>(members_llvm));
    st->is_opaque = false;

    st->internal_name.clear();
    st->internal_name.append(symbol.c_str());

    st->linkage = linkage;

    for (std::vector<Variable *>::iterator b = members_internal.begin(),
                                           e = members_internal.end();
            b != e;
            ++b) {
        st->addMember((*b)->name.c_str(), (*b)->type);
        delete (*b);
    }

    return true;
}