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; }
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; }