add explicit member func call, ready to merge new testcases

This commit is contained in:
2024-08-23 02:20:27 +00:00
parent 839d0ad11c
commit cb56e7a184
4 changed files with 152 additions and 10 deletions

View File

@ -244,7 +244,6 @@ class ICMPAction : public ActionItem {
}; };
class BlockItem : public LLVMIRItemBase { class BlockItem : public LLVMIRItemBase {
friend class IRBuilder; friend class IRBuilder;
friend void ArrangeConstArr(BlockItem &blk, class ConstantExpr_ASTNode *node, size_t &tmp_var_counter);
std::string label_full; std::string label_full;
std::vector<std::shared_ptr<ActionItem>> actions; std::vector<std::shared_ptr<ActionItem>> actions;
std::shared_ptr<JMPActionItem> exit_action; std::shared_ptr<JMPActionItem> exit_action;

View File

@ -138,6 +138,7 @@ class ClassDefScope : public ScopeBase {
std::unordered_map<std::string, ExprTypeInfo> member_variables; std::unordered_map<std::string, ExprTypeInfo> member_variables;
std::unordered_map<std::string, std::shared_ptr<FunctionScope>> member_functions; std::unordered_map<std::string, std::shared_ptr<FunctionScope>> member_functions;
IRClassInfo llvm_class_info; IRClassInfo llvm_class_info;
size_t arrange_counter;
bool add_variable(const std::string &name, const ExprTypeInfo &type) override { bool add_variable(const std::string &name, const ExprTypeInfo &type) override {
if (!VariableNameAvailable(name, 0)) { if (!VariableNameAvailable(name, 0)) {
return false; return false;
@ -150,6 +151,14 @@ class ClassDefScope : public ScopeBase {
throw SemanticError("Invalid Type", 1); throw SemanticError("Invalid Type", 1);
} }
member_variables[name] = type; member_variables[name] = type;
llvm_class_info.member_var_offset[name] = arrange_counter++;
size_t cur_element_size = 4;
ExprTypeInfo bool_std = IdentifierType("bool");
if (type == bool_std) {
cur_element_size = 1;
}
llvm_class_info.member_var_size.push_back(cur_element_size);
llvm_class_info.member_var_type.push_back(Type_AST2LLVM(type));
return true; return true;
} }
virtual ExprTypeInfo fetch_varaible(const std::string &name) override { virtual ExprTypeInfo fetch_varaible(const std::string &name) override {
@ -196,6 +205,9 @@ class ClassDefScope : public ScopeBase {
} }
return parent->VariableNameAvailable(name, ttl + 1); return parent->VariableNameAvailable(name, ttl + 1);
} }
public:
ClassDefScope() : arrange_counter(0) {}
}; };
class GlobalScope : public ScopeBase { class GlobalScope : public ScopeBase {
friend class Visitor; friend class Visitor;
@ -307,6 +319,15 @@ class GlobalScope : public ScopeBase {
} }
return parent->fetch_variable_for_IR(name); return parent->fetch_variable_for_IR(name);
} }
IRClassInfo fetch_class_info(const std::string &name) {
if (classes.find(name) == classes.end()) {
throw SemanticError("Undefined Identifier", 1);
}
auto &tmp = classes[name]->llvm_class_info;
tmp.class_name_raw = name;
tmp.ArrangeSpace();
return tmp;
}
public: public:
GlobalScope() { parent = nullptr; } GlobalScope() { parent = nullptr; }

View File

@ -117,13 +117,17 @@ struct LLVMIRCLASSTYPE {
using LLVMType = std::variant<LLVMIRIntType, LLVMIRPTRType, LLVMVOIDType, LLVMIRCLASSTYPE>; using LLVMType = std::variant<LLVMIRIntType, LLVMIRPTRType, LLVMVOIDType, LLVMIRCLASSTYPE>;
class IRClassInfo { class IRClassInfo {
public: public:
std::string class_name_raw; // This data must be provided by user std::string class_name_raw; // This data must be provided by user
std::vector<size_t> member_var_size; // This data must be provided by user. Each of them is the size of a member std::vector<size_t> member_var_size; // This data must be provided by user. Each of them is the size of a member
// variable, which must be in [1,4] // variable, which must be in [1,4]
std::vector<LLVMType> member_var_type; // This data must be provided by user
std::unordered_map<std::string, size_t> member_var_offset; // This data must be provided by user std::unordered_map<std::string, size_t> member_var_offset; // This data must be provided by user
std::vector<size_t> member_var_pos_after_align; std::vector<size_t> member_var_pos_after_align;
size_t class_size_after_align; size_t class_size_after_align;
bool alread_arranged;
void ArrangeSpace() { void ArrangeSpace() {
if (alread_arranged) return;
alread_arranged = true;
size_t cur_pos = 0; size_t cur_pos = 0;
size_t align_size = 1; size_t align_size = 1;
for (size_t cur_size : member_var_size) { for (size_t cur_size : member_var_size) {
@ -142,6 +146,7 @@ class IRClassInfo {
} }
} }
std::string GenerateFullName() { return "%.class." + class_name_raw; } std::string GenerateFullName() { return "%.class." + class_name_raw; }
IRClassInfo() : alread_arranged(false) {}
}; };
class IRVariableInfo { class IRVariableInfo {
public: public:

View File

@ -397,7 +397,56 @@ void IRBuilder::ActuralVisit(NewExpr_ASTNode *node) {
} }
void IRBuilder::ActuralVisit(AccessExpr_ASTNode *node) { void IRBuilder::ActuralVisit(AccessExpr_ASTNode *node) {
// TODO: Implement function body if (!node->is_function) {
node->base->accept(this);
std::string type_of_base = std::get<IdentifierType>(node->base->expr_type_info);
IRClassInfo class_info = global_scope->fetch_class_info(type_of_base);
std::string base_ptr = node->base->IR_result_full;
size_t idx = class_info.member_var_offset[node->member];
auto member_addr_cal = std::make_shared<GetElementPtrAction>();
cur_block->actions.push_back(member_addr_cal);
member_addr_cal->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
member_addr_cal->ty = LLVMIRCLASSTYPE{"%.class." + type_of_base};
member_addr_cal->ptr_full = base_ptr;
member_addr_cal->indices.push_back("0");
member_addr_cal->indices.push_back(std::to_string(idx));
if (node->is_requiring_lvalue) {
node->IR_result_full = member_addr_cal->result_full;
} else {
auto member_val_load = std::make_shared<LoadAction>();
cur_block->actions.push_back(member_val_load);
member_val_load->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
member_val_load->ty = class_info.member_var_type[idx];
member_val_load->ptr_full = member_addr_cal->result_full;
node->IR_result_full = member_val_load->result_full;
}
} else {
node->base->accept(this);
std::string type_of_base = std::get<IdentifierType>(node->base->expr_type_info);
std::string base_ptr = node->base->IR_result_full;
std::string func_name = type_of_base + "." + node->member;
std::vector<std::string> arg_val;
for (size_t i = 0; i < node->arguments.size(); i++) {
node->arguments[i]->accept(this);
arg_val.push_back(node->arguments[i]->IR_result_full);
}
auto call_act = std::make_shared<CallItem>();
cur_block->actions.push_back(call_act);
call_act->return_type = Type_AST2LLVM(node->expr_type_info);
if (!std::holds_alternative<LLVMVOIDType>(call_act->return_type)) {
call_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
}
call_act->func_name_raw = func_name;
call_act->args_ty.push_back(LLVMIRPTRType());
call_act->args_val_full.push_back(base_ptr);
for (size_t i = 0; i < arg_val.size(); i++) {
call_act->args_ty.push_back(Type_AST2LLVM(node->arguments[i]->expr_type_info));
call_act->args_val_full.push_back(arg_val[i]);
}
if (!std::holds_alternative<LLVMVOIDType>(call_act->return_type)) {
node->IR_result_full = call_act->result_full;
}
}
} }
void IRBuilder::ActuralVisit(IndexExpr_ASTNode *node) { void IRBuilder::ActuralVisit(IndexExpr_ASTNode *node) {
@ -740,6 +789,7 @@ void IRBuilder::ActuralVisit(ThisExpr_ASTNode *node) {
void IRBuilder::ActuralVisit(ParenExpr_ASTNode *node) { void IRBuilder::ActuralVisit(ParenExpr_ASTNode *node) {
node->expr->accept(this); // just visit it node->expr->accept(this); // just visit it
node->IR_result_full = node->expr->IR_result_full;
} }
void IRBuilder::ActuralVisit(IDExpr_ASTNode *node) { void IRBuilder::ActuralVisit(IDExpr_ASTNode *node) {
@ -846,34 +896,101 @@ void IRBuilder::ActuralVisit(ConstantExpr_ASTNode *node) {
std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src) { std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src) {
IRBuilder visitor; IRBuilder visitor;
visitor.prog = std::make_shared<ModuleItem>(); visitor.prog = std::make_shared<ModuleItem>();
auto tmp = std::make_shared<FunctionDeclareItem>(); auto tmp = std::make_shared<FunctionDeclareItem>(); // void* malloc(unsigned int size)
tmp->func_name_raw = "malloc"; tmp->func_name_raw = "malloc";
tmp->return_type = LLVMIRPTRType(); tmp->return_type = LLVMIRPTRType();
tmp->args.push_back(LLVMIRIntType(32)); tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp); visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>();
tmp = std::make_shared<FunctionDeclareItem>(); // void printInt(int n)
tmp->func_name_raw = "printInt"; tmp->func_name_raw = "printInt";
tmp->return_type = LLVMVOIDType(); tmp->return_type = LLVMVOIDType();
tmp->args.push_back(LLVMIRIntType(32)); tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp); visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>();
tmp = std::make_shared<FunctionDeclareItem>(); // void print(char *str)
tmp->func_name_raw = "print"; tmp->func_name_raw = "print";
tmp->return_type = LLVMVOIDType(); tmp->return_type = LLVMVOIDType();
tmp->args.push_back(LLVMIRPTRType()); tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp); visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>();
tmp = std::make_shared<FunctionDeclareItem>(); // void* _builtin_AllocateArray(int element_size, int element_num)
tmp->func_name_raw = ".builtin.AllocateArray"; tmp->func_name_raw = ".builtin.AllocateArray";
tmp->return_type = LLVMIRPTRType(); tmp->return_type = LLVMIRPTRType();
tmp->args.push_back(LLVMIRIntType(32)); tmp->args.push_back(LLVMIRIntType(32));
tmp->args.push_back(LLVMIRIntType(32)); tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp); visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>();
tmp = std::make_shared<FunctionDeclareItem>(); // void* _builtin_RecursiveAllocateArray(int dims_with_size,
// int element_size, int* dim_size)
tmp->func_name_raw = ".builtin.RecursiveAllocateArray"; tmp->func_name_raw = ".builtin.RecursiveAllocateArray";
tmp->return_type = LLVMIRPTRType(); tmp->return_type = LLVMIRPTRType();
tmp->args.push_back(LLVMIRIntType(32)); tmp->args.push_back(LLVMIRIntType(32));
tmp->args.push_back(LLVMIRIntType(32)); tmp->args.push_back(LLVMIRIntType(32));
tmp->args.push_back(LLVMIRPTRType()); tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp); visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // int _builtin_GetArrayLength(void* array)
tmp->func_name_raw = ".builtin.GetArrayLength";
tmp->return_type = LLVMIRIntType(32);
tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // int getInt()
tmp->func_name_raw = "getInt";
tmp->return_type = LLVMIRIntType(32);
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // char* getString()
tmp->func_name_raw = "getString";
tmp->return_type = LLVMIRPTRType();
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // char* toString(int n)
tmp->func_name_raw = "toString";
tmp->return_type = LLVMIRPTRType();
tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // void printlnInt(int n)
tmp->func_name_raw = "printlnInt";
tmp->return_type = LLVMVOIDType();
tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // void println(char *str)
tmp->func_name_raw = "println";
tmp->return_type = LLVMVOIDType();
tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // int string_length(char *self)
tmp->func_name_raw = "string.length";
tmp->return_type = LLVMIRIntType(32);
tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // char* string_substring(char *self,int left, int right)
tmp->func_name_raw = "string.substring";
tmp->return_type = LLVMIRPTRType();
tmp->args.push_back(LLVMIRPTRType());
tmp->args.push_back(LLVMIRIntType(32));
tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // int string_parseInt(char *self)
tmp->func_name_raw = "string.parseInt";
tmp->return_type = LLVMIRIntType(32);
tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp);
tmp = std::make_shared<FunctionDeclareItem>(); // int string_ord(char *self, int index)
tmp->func_name_raw = "string.ord";
tmp->return_type = LLVMIRIntType(32);
tmp->args.push_back(LLVMIRPTRType());
tmp->args.push_back(LLVMIRIntType(32));
visitor.prog->function_declares.push_back(tmp);
visitor.global_scope = std::dynamic_pointer_cast<GlobalScope>(src->current_scope); visitor.global_scope = std::dynamic_pointer_cast<GlobalScope>(src->current_scope);
if (!(visitor.global_scope)) throw std::runtime_error("global scope not found"); if (!(visitor.global_scope)) throw std::runtime_error("global scope not found");
visitor.visit(src.get()); visitor.visit(src.get());