bool FormProcDoParse(Units *units, Function *fn, llvm::BasicBlock *block, Node *node, bool get_address, bool prefixed_with_core, ParseResult *pr) { Context *ctx = units->top()->ctx; if (node->list->size() == 1) { pr->set(block, ctx->tr->type_void, NULL); return true; } for (std::vector<Node *>::iterator b = (node->list->begin() + 1), e = (node->list->end() - 1); b != e; ++b) { ParseResult local_pr; bool res = FormProcInstParse(units, fn, block, *b, get_address, false, NULL, &local_pr); if (!res) { return false; } ParseResult destruct_pr; res = Operation::Destruct(ctx, &local_pr, &destruct_pr); if (!res) { return false; } block = destruct_pr.block; } return FormProcInstParse(units, fn, block, *(node->list->end() - 1), get_address, false, NULL, pr); }
bool FormProcFuncallParse(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("funcall", node, 1, -1)) { return false; } std::vector<Node *> *lst = node->list; Node *fp_node = (*lst)[1]; ParseResult fp_pr; bool res = FormProcInstParse(units, fn, block, fp_node, get_address, false, NULL, &fp_pr); if (!res) { return false; } if (!fp_pr.type->points_to || !fp_pr.type->points_to->is_function) { std::string type_str; fp_pr.type->toString(&type_str); Error *e = new Error(IncorrectArgType, fp_node, "funcall", "function pointer", "1", type_str.c_str()); ctx->er->addError(e); return false; } return units->top()->fp->parseFunctionPointerCall(fn, node, &fp_pr, 2, NULL, pr); }
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); } }
bool FormProcMoveParse(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("cast", node, 1, 1)) { return false; } std::vector<Node *> *lst = node->list; Node *value_node = (*lst)[1]; ParseResult value_pr; bool res = FormProcInstParse(units, fn, block, value_node, false, false, NULL, &value_pr, true); if (!res) { return false; } res = Operation::Move(ctx, fn, &value_pr, pr); return res; }
Node * MacroProcessor::parsePotentialMacroCall(Node *n) { if (n->is_token || !n->is_list) { return n; } std::vector<Node *> *lst = n->list; if (lst->size() == 0) { return n; } Node *macro_name_node = (*lst)[0]; if (!macro_name_node->is_token) { return n; } const char *macro_name = macro_name_node->token->str_value.c_str(); Node *(*core_mac)(Context *ctx, Node *n); core_mac = (eq("setv")) ? &FormMacroSetvParse : (eq("@$")) ? &FormMacroArrayDerefParse : (eq(":@")) ? &FormMacroDerefStructParse : (eq("@:")) ? &FormMacroStructDerefParse : (eq("@:@")) ? &FormMacroDerefStructDerefParse : NULL; if (core_mac) { return core_mac(ctx, n); } Function *ffn = ctx->getFunction(macro_name, NULL, 1); if (!ffn) { return n; } bool made_temp = false; Function *global_fn = units->top()->getGlobalFunction(); if (!global_fn) { units->top()->makeTemporaryGlobalFunction(); global_fn = units->top()->getGlobalFunction(); made_temp = true; } std::vector<Type *> types; llvm::BasicBlock *block = &(global_fn->llvm_function->front()); int error_count = ctx->er->getErrorTypeCount(ErrorType::Error); for (std::vector<Node *>::iterator b = lst->begin() + 1, e = lst->end(); b != e; ++b) { ParseResult arg_pr; bool res = FormProcInstParse(units, global_fn, block, *b, false, false, NULL, &arg_pr); if (res) { /* Add the type. */ types.push_back(arg_pr.type); block = arg_pr.block; } else { /* Add a (p DNode) to types. */ types.push_back(ctx->tr->type_pdnode); } } ctx->er->popErrors(error_count); if (made_temp) { units->top()->removeTemporaryGlobalFunction(); } ffn = ctx->getFunction(macro_name, &types, 1); if (!ffn) { return n; } Node *mac_node = parseMacroCall(n, ffn); if (!mac_node) { return NULL; } /* If a macro node was got, and it's a list containing two * elements, and the first element is 'do', then just return the * second element. */ if ((!mac_node->is_token) && (mac_node->list->size() == 2) && ((*mac_node->list)[0]->is_token) && ((*mac_node->list)[0] ->token->str_value.compare("do") == 0)) { return parsePotentialMacroCall((*mac_node->list)[1]); } else { return parsePotentialMacroCall(mac_node); } }
bool FormProcArefParse(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("$", node, 2, 2)) { return false; } std::vector<Node *> *lst = node->list; Node *array_node = (*lst)[1]; Node *index_node = (*lst)[2]; ParseResult initial_array_pr; bool res = FormProcInstParse(units, fn, block, array_node, false, false, NULL, &initial_array_pr); if (!res) { return false; } if (!(initial_array_pr.type->array_type || initial_array_pr.type->points_to)) { std::string type_str; initial_array_pr.type->toString(&type_str); Error *e = new Error(IncorrectArgType, array_node, "$", "a pointer or array", "1", type_str.c_str()); ctx->er->addError(e); return false; } ParseResult array_pr; bool is_array; if (initial_array_pr.type->array_type) { initial_array_pr.getAddressOfValue(ctx, &array_pr); array_pr.type = ctx->tr->getPointerType(initial_array_pr.type->array_type); is_array = true; } else { initial_array_pr.copyTo(&array_pr); is_array = false; } ParseResult index_pr; res = FormProcInstParse(units, fn, array_pr.block, index_node, false, false, NULL, &index_pr); if (!res) { return false; } if (!index_pr.type->isIntegerType()) { std::string type_str; index_pr.type->toString(&type_str); Error *e = new Error(IncorrectType, index_node, "integer", type_str.c_str()); ctx->er->addError(e); return false; } llvm::IRBuilder<> builder(index_pr.block); std::vector<llvm::Value *> indices; if (!is_array) { indices.push_back( llvm::cast<llvm::Value>(index_pr.getValue(ctx))); } else { STL::push_back2( &indices, ctx->nt->getLLVMZero(), llvm::cast<llvm::Value>(index_pr.getValue(ctx))); } llvm::Value *array_value = array_pr.getValue(ctx); if (array_pr.type->is_array) { pr->type = ctx->tr->getPointerType(array_pr.type->array_type); } else { pr->type = array_pr.type; } llvm::Value *index_ptr = builder.Insert(createGEP(array_value, indices)); pr->block = index_pr.block; pr->set(pr->block, pr->type, index_ptr); array_pr.block = index_pr.block; ParseResult destruct_pr; res = Operation::Destruct(ctx, &array_pr, &destruct_pr); if (!res) { return false; } index_pr.block = destruct_pr.block; res = Operation::Destruct(ctx, &index_pr, &destruct_pr); if (!res) { return false; } pr->block = destruct_pr.block; return true; }
bool FormLiteralStructParse(Units *units, Function *fn, llvm::BasicBlock *block, Node *node, const char *struct_name, Struct *st, Type *st_type, bool get_address, ParseResult *pr) { Context *ctx = units->top()->ctx; if (!node->is_list) { Error *e = new Error(UnexpectedElement, node, "list", "struct initialisers", "atom"); ctx->er->addError(e); return false; } std::vector<Node *> *lst = node->list; llvm::IRBuilder<> builder(block); llvm::Value *storage = llvm::cast<llvm::Value>(builder.CreateAlloca(st->type)); for (std::vector<Node *>::iterator b = lst->begin(), e = lst->end(); b != e; ++b) { Node *member_node = (*b); if (!member_node->is_list) { Error *e = new Error(UnexpectedElement, member_node, "list", "struct initialiser", "atom"); ctx->er->addError(e); return false; } std::vector<Node *> *member_lst = member_node->list; if (member_lst->size() != 2) { Error *e = new Error(UnexpectedElement, member_node, "list", "struct initialiser", "atom"); ctx->er->addError(e); return false; } Node *name_node = (*member_lst)[0]; Node *value_node = (*member_lst)[1]; if (!name_node->is_token) { Error *e = new Error(UnexpectedElement, name_node, "atom", "struct field name", "list"); ctx->er->addError(e); return false; } const char *name = name_node->token->str_value.c_str(); Type *type = st->nameToType(name); if (!type) { Error *e = new Error(FieldDoesNotExistInStruct, name_node, name, struct_name); ctx->er->addError(e); return false; } int index = st->nameToIndex(name); std::vector<llvm::Value *> indices; STL::push_back2(&indices, ctx->nt->getLLVMZero(), ctx->nt->getNativeInt(index)); llvm::Value *storage_ptr = builder.CreateGEP(storage, llvm::ArrayRef<llvm::Value*>(indices)); ParseResult value_pr; bool res = FormProcInstParse(units, fn, block, value_node, false, false, NULL, &value_pr); if (!res) { return false; } if (!value_pr.type->isEqualTo(type, 1)) { if ((type->isIntegerType() && value_pr.type->isIntegerType()) || (type->isFloatingPointType() && value_pr.type->isFloatingPointType())) { ParseResult cast_pr; res = Operation::Cast(ctx, value_pr.block, value_pr.value, value_pr.type, type, member_node, 0, &cast_pr); if (!res) { return false; } cast_pr.copyTo(&value_pr); } else { std::string wanted; std::string got; type->toString(&wanted); value_pr.type->toString(&got); Error *e = new Error(IncorrectType, name_node, wanted.c_str(), got.c_str()); ctx->er->addError(e); return false; } } block = value_pr.block; builder.SetInsertPoint(block); builder.CreateStore(value_pr.value, storage_ptr); } if (get_address) { pr->set(block, ctx->tr->getPointerType(st_type), storage); } else { llvm::Value *final_value = builder.CreateLoad(storage); pr->set(block, st_type, final_value); pr->address_of_value = storage; pr->value_is_lvalue = true; } return true; }