write all functions

This commit is contained in:
2024-08-24 01:28:40 +00:00
parent 8781d58776
commit 2168e402d3
3 changed files with 186 additions and 5 deletions

View File

@ -336,6 +336,7 @@ class PhiItem : public ActionItem {
} }
}; };
class SelectItem : public ActionItem { class SelectItem : public ActionItem {
friend class IRBuilder;
std::string result_full; std::string result_full;
std::string cond_full; std::string cond_full;
std::string true_val_full; std::string true_val_full;
@ -449,6 +450,7 @@ class FunctionDeclareItem : public LLVMIRItemBase {
} }
}; };
class ConstStrItem : public LLVMIRItemBase { class ConstStrItem : public LLVMIRItemBase {
friend std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src);
friend class IRBuilder; friend class IRBuilder;
std::string string_raw; std::string string_raw;
size_t const_str_id; size_t const_str_id;

View File

@ -181,7 +181,7 @@ inline LLVMType Type_AST2LLVM(const ExprTypeInfo &src) {
return LLVMIRPTRType(); return LLVMIRPTRType();
} }
inline std::string StringLiteralDeEscape(const std::string src) { inline std::string StringLiteralDeEscape(const std::string &src) {
std::stringstream ss; std::stringstream ss;
for (size_t i = 1; i < src.size() - 1; i++) { for (size_t i = 1; i < src.size() - 1; i++) {
if (src[i] != '\\') if (src[i] != '\\')
@ -208,3 +208,36 @@ inline std::string StringLiteralDeEscape(const std::string src) {
} }
return ss.str(); return ss.str();
} }
inline std::string FmtStrLiteralDeEscape(const std::string &src) {
std::stringstream ss;
for (size_t i = 0; i < src.size(); i++) {
if (src[i] == '\\') {
i++;
if (src[i] == 'n')
ss << '\n';
else if (src[i] == 'r')
ss << '\r';
else if (src[i] == 't')
ss << '\t';
else if (src[i] == '\\')
ss << '\\';
else if (src[i] == '\'')
ss << '\'';
else if (src[i] == '\"')
ss << '\"';
else if (src[i] == '0')
ss << '\0';
else
throw std::runtime_error("Invalid escape character");
} else if (src[i] == '$') {
i++;
if (src[i] == '$')
ss << '$';
else
throw std::runtime_error("Invalid escape character");
} else
ss << src[i];
}
return ss.str();
}

View File

@ -798,6 +798,37 @@ void IRBuilder::ActuralVisit(RLExpr_ASTNode *node) {
void IRBuilder::ActuralVisit(GGLLExpr_ASTNode *node) { void IRBuilder::ActuralVisit(GGLLExpr_ASTNode *node) {
node->left->accept(this); node->left->accept(this);
node->right->accept(this); node->right->accept(this);
ExprTypeInfo string_std = IdentifierType("string");
if (node->left->expr_type_info == string_std) {
auto strcmp_call = std::make_shared<CallItem>();
cur_block->actions.push_back(strcmp_call);
strcmp_call->func_name_raw = "strcmp";
strcmp_call->return_type = LLVMIRIntType(32);
strcmp_call->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
strcmp_call->args_ty.push_back(LLVMIRPTRType());
strcmp_call->args_val_full.push_back(node->left->IR_result_full);
strcmp_call->args_ty.push_back(LLVMIRPTRType());
strcmp_call->args_val_full.push_back(node->right->IR_result_full);
auto cmp_act = std::make_shared<ICMPAction>();
cur_block->actions.push_back(cmp_act);
if (node->op == ">=") {
cmp_act->op = "sge";
} else if (node->op == ">") {
cmp_act->op = "sgt";
} else if (node->op == "<=") {
cmp_act->op = "sle";
} else if (node->op == "<") {
cmp_act->op = "slt";
} else {
throw std::runtime_error("unknown GGLL operator");
}
cmp_act->operand1_full = strcmp_call->result_full;
cmp_act->operand2_full = "0";
cmp_act->type = LLVMIRIntType(32);
cmp_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
node->IR_result_full = cmp_act->result_full;
return;
}
auto act = std::make_shared<ICMPAction>(); auto act = std::make_shared<ICMPAction>();
cur_block->actions.push_back(act); cur_block->actions.push_back(act);
if (node->op == ">=") { if (node->op == ">=") {
@ -816,12 +847,36 @@ void IRBuilder::ActuralVisit(GGLLExpr_ASTNode *node) {
act->type = Type_AST2LLVM(node->left->expr_type_info); act->type = Type_AST2LLVM(node->left->expr_type_info);
act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++); act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
node->IR_result_full = act->result_full; node->IR_result_full = act->result_full;
// TODO: string comparison
} }
void IRBuilder::ActuralVisit(NEExpr_ASTNode *node) { void IRBuilder::ActuralVisit(NEExpr_ASTNode *node) {
node->left->accept(this); node->left->accept(this);
node->right->accept(this); node->right->accept(this);
ExprTypeInfo string_std = IdentifierType("string");
if (node->left->expr_type_info == string_std) {
auto strcmp_call = std::make_shared<CallItem>();
cur_block->actions.push_back(strcmp_call);
strcmp_call->func_name_raw = "strcmp";
strcmp_call->return_type = LLVMIRIntType(32);
strcmp_call->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
strcmp_call->args_ty.push_back(LLVMIRPTRType());
strcmp_call->args_val_full.push_back(node->left->IR_result_full);
strcmp_call->args_ty.push_back(LLVMIRPTRType());
strcmp_call->args_val_full.push_back(node->right->IR_result_full);
auto cmp_act = std::make_shared<ICMPAction>();
cur_block->actions.push_back(cmp_act);
if (node->op == "!=") {
cmp_act->op = "ne";
} else {
cmp_act->op = "eq";
}
cmp_act->operand1_full = strcmp_call->result_full;
cmp_act->operand2_full = "0";
cmp_act->type = LLVMIRIntType(32);
cmp_act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
node->IR_result_full = cmp_act->result_full;
return;
}
auto act = std::make_shared<ICMPAction>(); auto act = std::make_shared<ICMPAction>();
cur_block->actions.push_back(act); cur_block->actions.push_back(act);
if (node->op == "!=") { if (node->op == "!=") {
@ -836,7 +891,6 @@ void IRBuilder::ActuralVisit(NEExpr_ASTNode *node) {
act->type = Type_AST2LLVM(node->left->expr_type_info); act->type = Type_AST2LLVM(node->left->expr_type_info);
act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++); act->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
node->IR_result_full = act->result_full; node->IR_result_full = act->result_full;
// TODO: string comparison
} }
void IRBuilder::ActuralVisit(BAndExpr_ASTNode *node) { void IRBuilder::ActuralVisit(BAndExpr_ASTNode *node) {
@ -1123,8 +1177,81 @@ void IRBuilder::ActuralVisit(FunctionCallExpr_ASTNode *node) {
} }
void IRBuilder::ActuralVisit(FormattedStringExpr_ASTNode *node) { void IRBuilder::ActuralVisit(FormattedStringExpr_ASTNode *node) {
// TODO: Implement function body for (size_t i = 0; i < node->literals.size(); i++) {
throw std::runtime_error("formatted string not supported"); std::string str;
if (i == 0)
str = node->literals[i].substr(2, node->literals[i].size() - 3);
else
str = node->literals[i].substr(1, node->literals[i].size() - 2);
str = FmtStrLiteralDeEscape(str);
if (const_str_dict.find(str) == const_str_dict.end()) {
const_str_dict[str] = const_str_counter++;
auto const_str_item = std::make_shared<ConstStrItem>();
prog->const_strs.push_back(const_str_item);
const_str_item->string_raw = str;
const_str_item->const_str_id = const_str_dict[str];
}
}
ExprTypeInfo string_std = IdentifierType("string");
ExprTypeInfo int_std = IdentifierType("int");
ExprTypeInfo bool_std = IdentifierType("bool");
std::string res =
"@.str." +
std::to_string(const_str_dict[FmtStrLiteralDeEscape(node->literals[0].substr(2, node->literals[0].size() - 3))]);
if (node->exprs.size() + 1 != node->literals.size()) throw std::runtime_error("formatted string error");
for (size_t i = 0; i < node->exprs.size(); i++) {
node->exprs[i]->accept(this);
std::string str_res = node->exprs[i]->IR_result_full;
if (node->exprs[i]->expr_type_info == string_std) {
; // just do nothing
} else if (node->exprs[i]->expr_type_info == int_std) {
auto call = std::make_shared<CallItem>();
cur_block->actions.push_back(call);
call->func_name_raw = "toString";
call->return_type = LLVMIRPTRType();
call->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
call->args_ty.push_back(LLVMIRIntType(32));
call->args_val_full.push_back(str_res);
str_res = call->result_full;
} else if (node->exprs[i]->expr_type_info == bool_std) {
auto select = std::make_shared<SelectItem>();
cur_block->actions.push_back(select);
select->result_full = "%.var.tmp." + std::to_string(tmp_var_counter++);
select->ty = LLVMIRPTRType();
select->cond_full = str_res;
select->true_val_full = "@.str." + std::to_string(const_str_dict["true"]);
select->false_val_full = "@.str." + std::to_string(const_str_dict["false"]);
str_res = select->result_full;
} else {
throw std::runtime_error("formatted string error");
}
std::string tmp = "%.var.tmp." + std::to_string(tmp_var_counter++);
auto strcat1 = std::make_shared<CallItem>();
cur_block->actions.push_back(strcat1);
strcat1->func_name_raw = ".builtin.strcat";
strcat1->return_type = LLVMIRPTRType();
strcat1->result_full = tmp;
strcat1->args_ty.push_back(LLVMIRPTRType());
strcat1->args_val_full.push_back(res);
strcat1->args_ty.push_back(LLVMIRPTRType());
strcat1->args_val_full.push_back(str_res);
res = tmp;
tmp = "%.var.tmp." + std::to_string(tmp_var_counter++);
auto strcat2 = std::make_shared<CallItem>();
cur_block->actions.push_back(strcat2);
strcat2->func_name_raw = ".builtin.strcat";
strcat2->return_type = LLVMIRPTRType();
strcat2->result_full = tmp;
strcat2->args_ty.push_back(LLVMIRPTRType());
strcat2->args_val_full.push_back(res);
strcat2->args_ty.push_back(LLVMIRPTRType());
strcat2->args_val_full.push_back(
"@.str." +
std::to_string(
const_str_dict[FmtStrLiteralDeEscape(node->literals[i + 1].substr(1, node->literals[i + 1].size() - 2))]));
res = tmp;
}
node->IR_result_full = res;
} }
void IRBuilder::ActuralVisit(ConstantExpr_ASTNode *node) { void IRBuilder::ActuralVisit(ConstantExpr_ASTNode *node) {
@ -1273,6 +1400,25 @@ std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src) {
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 strcmp(const char *str1, const char *str2);
tmp->func_name_raw = "strcmp";
tmp->return_type = LLVMIRIntType(32);
tmp->args.push_back(LLVMIRPTRType());
tmp->args.push_back(LLVMIRPTRType());
visitor.prog->function_declares.push_back(tmp);
visitor.const_str_dict["true"] = visitor.const_str_counter++;
auto const_str_item = std::make_shared<ConstStrItem>();
visitor.prog->const_strs.push_back(const_str_item);
const_str_item->string_raw = "true";
const_str_item->const_str_id = visitor.const_str_dict["true"];
visitor.const_str_dict["false"] = visitor.const_str_counter++;
const_str_item = std::make_shared<ConstStrItem>();
visitor.prog->const_strs.push_back(const_str_item);
const_str_item->string_raw = "false";
const_str_item->const_str_id = visitor.const_str_dict["false"];
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());