1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

Add pragmas to funC for precise control of computation order (#589)

* FunC pragmas: allow-post-modification and compute-asm-ltr

* Warn if #pragma is enabled only in included files

* Add tests for new pragmas

* Add special ops for "allow-post-modification" only when needed

* Update FunC version to 0.4.1

* Allow empty inlines (#10)

Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
EmelyanenkoK 2023-01-13 12:45:04 +03:00 committed by GitHub
parent 6b49d6a382
commit 653c88aa9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 344 additions and 61 deletions

View file

@ -261,6 +261,12 @@ void parse_const_decl(Lexer& lex) {
}
lex.next();
CodeBlob code;
if (pragma_allow_post_modification.enabled()) {
code.flags |= CodeBlob::_AllowPostModification;
}
if (pragma_compute_asm_ltr.enabled()) {
code.flags |= CodeBlob::_ComputeAsmLtr;
}
// Handles processing and resolution of literals and consts
auto x = parse_expr(lex, code, false); // also does lex.next() !
if (x->flags != Expr::_IsRvalue) {
@ -1210,6 +1216,12 @@ blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code) {
CodeBlob* parse_func_body(Lexer& lex, FormalArgList arg_list, TypeExpr* ret_type) {
lex.expect('{');
CodeBlob* blob = new CodeBlob{ret_type};
if (pragma_allow_post_modification.enabled()) {
blob->flags |= CodeBlob::_AllowPostModification;
}
if (pragma_compute_asm_ltr.enabled()) {
blob->flags |= CodeBlob::_ComputeAsmLtr;
}
blob->import_params(std::move(arg_list));
blk_fl::val res = blk_fl::init;
bool warned = false;
@ -1676,6 +1688,10 @@ void parse_pragma(Lexer& lex) {
}
func_ver_test = lex.cur().str;
lex.next();
} else if (pragma_name == pragma_allow_post_modification.name()) {
pragma_allow_post_modification.enable(lex.cur().loc);
} else if (pragma_name == pragma_compute_asm_ltr.name()) {
pragma_compute_asm_ltr.enable(lex.cur().loc);
} else {
lex.cur().error(std::string{"unknown pragma `"} + pragma_name + "`");
}
@ -1684,7 +1700,7 @@ void parse_pragma(Lexer& lex) {
std::vector<const src::FileDescr*> source_fdescr;
std::vector<std::string> source_files;
std::map<std::string, src::FileDescr*> source_files;
std::stack<src::SrcLocation> inclusion_locations;
void parse_include(Lexer& lex, const src::FileDescr* fdescr) {
@ -1700,7 +1716,7 @@ void parse_include(Lexer& lex, const src::FileDescr* fdescr) {
}
lex.next();
lex.expect(';');
if (!parse_source_file(val.c_str(), include)) {
if (!parse_source_file(val.c_str(), include, false)) {
include.error(std::string{"failed parsing included file `"} + val + "`");
}
}
@ -1724,7 +1740,7 @@ bool parse_source(std::istream* is, src::FileDescr* fdescr) {
return true;
}
bool parse_source_file(const char* filename, src::Lexem lex) {
bool parse_source_file(const char* filename, src::Lexem lex, bool is_main) {
if (!filename || !*filename) {
auto msg = "source file name is an empty string";
if (lex.tp) {
@ -1741,7 +1757,9 @@ bool parse_source_file(const char* filename, src::Lexem lex) {
return false;
}
std::string real_filename = path_res.move_as_ok();
if (std::count(source_files.begin(), source_files.end(), real_filename)) {
auto it = source_files.find(real_filename);
if (it != source_files.end()) {
it->second->is_main |= is_main;
if (verbosity >= 2) {
if (lex.tp) {
lex.loc.show_warning(std::string{"skipping file "} + real_filename + " because it was already included");
@ -1755,8 +1773,9 @@ bool parse_source_file(const char* filename, src::Lexem lex) {
funC::generated_from += std::string{"incl:"};
}
funC::generated_from += std::string{"`"} + filename + "` ";
source_files.push_back(real_filename);
src::FileDescr* cur_source = new src::FileDescr{filename};
source_files[real_filename] = cur_source;
cur_source->is_main = is_main;
source_fdescr.push_back(cur_source);
std::ifstream ifs{filename};
if (ifs.fail()) {
@ -1775,6 +1794,7 @@ bool parse_source_file(const char* filename, src::Lexem lex) {
bool parse_source_stdin() {
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
cur_source->is_main = true;
source_fdescr.push_back(cur_source);
return parse_source(&std::cin, cur_source);
}