Exemple #1
0
bool FormProcVaArgParse(Units *units, Function *fn,
                        llvm::BasicBlock *block, Node *node,
                        bool get_address, bool prefixed_with_core,
                        ParseResult *pr) {
    Context *ctx = units->top()->ctx;

    if (!ctx->er->assertArgNums("va-arg", node, 2, 2)) {
        return false;
    }

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

    ParseResult arglist_pr;
    bool res = FormProcInstParse(units, fn, block, (*lst)[1], false,
                                 false, NULL, &arglist_pr);
    if (!res) {
        return false;
    }

    Type *type = FormTypeParse(units, (*lst)[2], false, false);
    if (!type) {
        return false;
    }

    llvm::Type *llvm_type = ctx->toLLVMType(type, NULL, false, false);
    if (!llvm_type) {
        return false;
    }

    if (!units->top()->is_x86_64) {
        /* Use the default va-arg intrinsic implementation. */
        llvm::IRBuilder<> builder(block);
        llvm::Value *res =
            builder.CreateVAArg(arglist_pr.getValue(ctx), llvm_type);
        pr->set(arglist_pr.block, type, res);
        return true;
    } else {
        return parseVaArg64(units, fn, type, llvm_type, &arglist_pr,
                            pr);
    }
}
Exemple #2
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;
}
Exemple #3
0
bool
FormTopLevelEnumParse(Units *units, Node *node)
{
    Context *ctx = units->top()->ctx;

    Node *top = (*node->list)[2];
    const char *name = (*node->list)[1]->token->str_value.c_str();

    std::vector<Node *> *lst = top->list;
    Node *linkage_node   = (*lst)[1];
    Node *enum_type_node = (*lst)[2];
    Node *elements_node  = (*lst)[3];

    if (lst->size() < 4) {
        Error *e = new Error(IncorrectMinimumNumberOfArgs, top,
                             "enum", 3, (int) lst->size() - 1);
        ctx->er->addError(e);
        return false;
    }

    int linkage = FormLinkageEnumParse(ctx, linkage_node);
    if (!linkage) {
        return false;
    }

    Type *enum_type = FormTypeParse(units, enum_type_node, false, false);
    if (!enum_type) {
        return false;
    }
    if (!enum_type->isIntegerType()) {
        Error *e = new Error(EnumTypeMustBeInteger, enum_type_node);
        ctx->er->addError(e);
        return false;
    }

    llvm::Type *llvm_enum_type = ctx->toLLVMType(enum_type, NULL, false);
    if (!llvm_enum_type) {
        return false;
    }

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

    Enum *enum_obj = new Enum();
    enum_obj->once_tag = units->top()->once_tag;
    enum_obj->linkage  = linkage;

    for (std::vector<Node *>::iterator b = elements_node->list->begin(),
                                       e = elements_node->list->end();
            b != e;
            ++b) {
        Node *n = (*b);

        n = isValidEnumElement(units, n);
        if (!n) {
            return false;
        }
        bool res;
        if (n->is_token) {
            res = enum_obj->addMember(n->token->str_value.c_str());
        } else {
            std::vector<Node *> *lst = n->list;
            Node *token_node  = (*lst)[0];
            Node *number_node = (*lst)[1];

            llvm::ConstantInt *c =
                ctx->nt->getConstantInt(
                    llvm::cast<llvm::IntegerType>(llvm_enum_type),
                    number_node->token->str_value.c_str()
                );
            int index = (int) c->getLimitedValue();
            res = enum_obj->addMember(token_node->token->str_value.c_str(), index);
        }
        if (!res) {
            Error *e = new Error(RedeclarationOfEnumElement,
                                 n, n->token->str_value.c_str());
            ctx->er->addError(e);
            return false;
        }
    }

    bool res = ctx->ns()->addEnum(name, enum_obj);
    if (!res) {
        Error *e = new Error(RedeclarationOfEnum, top, name);
        ctx->er->addError(e);
        return false;
    }

    Struct *enum_st = new Struct();
    enum_st->addMember("_enum_value", enum_type);
    enum_st->once_tag = units->top()->once_tag;
    enum_st->linkage =
        (linkage == EnumLinkage::Extern)
            ? StructLinkage::Extern
            : StructLinkage::Intern;

    std::vector<llvm::Type*> elements_llvm;
    elements_llvm.push_back(llvm_enum_type);

    llvm::StructType *llvm_new_struct =
        llvm::StructType::create(llvm::getGlobalContext(), "new_enum_stuct");
    llvm_new_struct->setBody(elements_llvm);

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

    std::string llvm_name;
    llvm_name.append("struct_");
    llvm_name.append(symbol);

    enum_st->symbol.append(llvm_name);

    llvm_new_struct->setName(llvm_name.c_str());
    if (llvm_new_struct->getName() != llvm::StringRef(llvm_name)) {
        Error *e = new Error(RedeclarationOfStruct, top, name);
        ctx->er->addError(e);
        return false;
    }

    enum_st->type = llvm_new_struct;

    res = ctx->ns()->addStruct(name, enum_st);
    if (!res) {
        Error *e = new Error(RedeclarationOfStruct, top, name);
        ctx->er->addError(e);
        return false;
    }

    Type *final_enum_type = new Type();
    final_enum_type->struct_name = name;
    ctx->setNamespacesForEnum(name, &(final_enum_type->namespaces));

    int final_linkage =
        (linkage == EnumLinkage::Extern)
            ? Linkage::Extern
            : Linkage::Intern;

    BasicTypes::addEnum(ctx, units->top()->module, &(units->top()->once_tag),
                        final_enum_type, enum_type, llvm_enum_type,
                        final_linkage);

    return true;
}