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