summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/crate.cpp23
-rw-r--r--src/ast/crate.hpp3
-rw-r--r--src/expand/format_args.cpp2
-rw-r--r--src/hir/from_ast_expr.cpp2
-rw-r--r--src/main.cpp11
-rw-r--r--src/trans/codegen_c.cpp246
6 files changed, 198 insertions, 89 deletions
diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp
index 394cd47b..f003a00b 100644
--- a/src/ast/crate.cpp
+++ b/src/ast/crate.cpp
@@ -8,6 +8,9 @@
#include <hir/main_bindings.hpp> // HIR_Deserialise
#include <fstream>
+::std::vector<::std::string> AST::g_crate_load_dirs = { };
+::std::map<::std::string, ::std::string> AST::g_crate_overrides;
+
namespace {
bool check_item_cfg(const ::AST::MetaItems& attrs)
{
@@ -99,15 +102,23 @@ void Crate::load_externs()
void Crate::load_extern_crate(Span sp, const ::std::string& name)
{
DEBUG("Loading crate '" << name << "'");
- // TODO: Search a list of load paths for the crate
- ::std::vector< ::std::string> paths { "output/", "output/test_deps/" };
::std::string path;
- for(const auto& p : paths){
- path = p + "lib" + name + ".hir";
+ auto it = g_crate_overrides.find(name);
+ if(it != g_crate_overrides.end())
+ {
+ path = it->second;
+ }
+ else
+ {
+ // Search a list of load paths for the crate
+ for(const auto& p : g_crate_load_dirs)
+ {
+ path = p + "/lib" + name + ".hir";
- if( ::std::ifstream(path).good() ) {
- break ;
+ if( ::std::ifstream(path).good() ) {
+ break ;
+ }
}
}
if( !::std::ifstream(path).good() ) {
diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp
index f9594a83..53dea1b9 100644
--- a/src/ast/crate.hpp
+++ b/src/ast/crate.hpp
@@ -89,4 +89,7 @@ public:
const MacroRules* find_macro_rules(const ::std::string& name) const;
};
+extern ::std::vector<::std::string> g_crate_load_dirs;
+extern ::std::map<::std::string, ::std::string> g_crate_overrides;
+
} // namespace AST
diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp
index 92afcbb2..e4c02b8b 100644
--- a/src/expand/format_args.cpp
+++ b/src/expand/format_args.cpp
@@ -477,7 +477,7 @@ class CFormatArgsExpander:
auto expr_tt = TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, Parse_Expr0(lex).release()) ));
- auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), named_args.size()) );
+ auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), static_cast<unsigned>(named_args.size())) );
if( ins_rv.second == false ) {
ERROR(sp, E0000, "Duplicate definition of named argument `" << ins_rv.first->first << "`");
}
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index 9bbb0418..545873ed 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -441,6 +441,8 @@ struct LowerHIR_ExprNode_Visitor:
case CORETYPE_U32: return ::HIR::CoreType::U32;
case CORETYPE_I64: return ::HIR::CoreType::I64;
case CORETYPE_U64: return ::HIR::CoreType::U64;
+ case CORETYPE_I128: return ::HIR::CoreType::I128;
+ case CORETYPE_U128: return ::HIR::CoreType::U128;
case CORETYPE_INT: return ::HIR::CoreType::Isize;
case CORETYPE_UINT: return ::HIR::CoreType::Usize;
diff --git a/src/main.cpp b/src/main.cpp
index 7b1d94be..b883a828 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -224,6 +224,11 @@ int main(int argc, char *argv[])
// Load external crates.
CompilePhaseV("LoadCrates", [&]() {
+ // Hacky!
+ for(const auto& ld : params.lib_search_dirs)
+ {
+ AST::g_crate_load_dirs.push_back(ld);
+ }
crate.load_externs();
});
@@ -570,6 +575,12 @@ int main(int argc, char *argv[])
// ::std::cerr << "Internal Compiler Error: " << e << ::std::endl;
// return 2;
//}
+
+ // TODO: Make this conditional
+#if 0
+ ::std::cout << "Press enter to exit..." << ::std::endl;
+ ::std::cin.get();
+#endif
return 0;
}
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 973aa33a..b7c3806a 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -499,7 +499,9 @@ namespace {
break;
case Compiler::Msvc:
is_windows = true;
+ // TODO: Look up these paths in the registry and use CreateProcess instead of system
args.push_back(cache_str( detect_msvc().path_vcvarsall ));
+ //args.push_back("amd64");
args.push_back("&");
args.push_back("cl.exe");
args.push_back("/nologo");
@@ -568,8 +570,9 @@ namespace {
}
//DEBUG("- " << cmd_ss.str());
::std::cout << "Running comamnd - " << cmd_ss.str() << ::std::endl;
- if( system(cmd_ss.str().c_str()) )
+ if( system(cmd_ss.str().c_str()) != 0 )
{
+ ::std::cerr << "C Compiler failed to execute" << ::std::endl;
abort();
}
}
@@ -2036,82 +2039,17 @@ namespace {
if( e.flag_idx != ~0u )
m_of << indent << "}\n";
break; }
- case ::MIR::Statement::TAG_Asm: {
- const auto& e = stmt.as_Asm();
-
- struct H {
- static bool has_flag(const ::std::vector<::std::string>& flags, const char* des) {
- return ::std::find_if(flags.begin(), flags.end(), [des](const auto&x){return x==des;}) != flags.end();
- }
- static const char* convert_reg(const char* r) {
- if( ::std::strcmp(r, "{eax}") == 0 || ::std::strcmp(r, "{rax}") == 0 ) {
- return "a";
- }
- else {
- return r;
- }
- }
- };
- bool is_volatile = H::has_flag(e.flags, "volatile");
- bool is_intel = H::has_flag(e.flags, "intel");
-
- m_of << indent << "__asm__ ";
- if(is_volatile) m_of << "__volatile__";
- // TODO: Convert format string?
- // TODO: Use a C-specific escaper here.
- m_of << "(\"" << (is_intel ? ".syntax intel; " : "");
- for(auto it = e.tpl.begin(); it != e.tpl.end(); ++it)
- {
- if( *it == '\n' )
- m_of << ";\\n";
- else if( *it == '"' )
- m_of << "\\\"";
- else if( *it == '\\' )
- m_of << "\\\\";
- else if( *it == '/' && *(it+1) == '/' )
- {
- while( it != e.tpl.end() || *it == '\n' )
- ++it;
- -- it;
- }
- else if( *it == '%' && *(it+1) == '%' )
- m_of << "%";
- else if( *it == '%' && !isdigit(*(it+1)) )
- m_of << "%%";
- else
- m_of << *it;
- }
- m_of << (is_intel ? ".syntax att; " : "") << "\"";
- m_of << ": ";
- for(unsigned int i = 0; i < e.outputs.size(); i ++ )
- {
- const auto& v = e.outputs[i];
- if( i != 0 ) m_of << ", ";
- m_of << "\"";
- switch(v.first[0])
- {
- case '=': m_of << "="; break;
- case '+': m_of << "+"; break;
- default: MIR_TODO(mir_res, "Handle asm! output leader '" << v.first[0] << "'");
- }
- m_of << H::convert_reg(v.first.c_str()+1);
- m_of << "\"("; emit_lvalue(v.second); m_of << ")";
- }
- m_of << ": ";
- for(unsigned int i = 0; i < e.inputs.size(); i ++ )
- {
- const auto& v = e.inputs[i];
- if( i != 0 ) m_of << ", ";
- m_of << "\"" << v.first << "\"("; emit_lvalue(v.second); m_of << ")";
- }
- m_of << ": ";
- for(unsigned int i = 0; i < e.clobbers.size(); i ++ )
+ case ::MIR::Statement::TAG_Asm:
+ switch(m_compiler)
{
- if( i != 0 ) m_of << ", ";
- m_of << "\"" << e.clobbers[i] << "\"";
+ case Compiler::Gcc:
+ this->emit_asm_gcc(mir_res, stmt.as_Asm(), indent_level);
+ break;
+ case Compiler::Msvc:
+ this->emit_asm_msvc(mir_res, stmt.as_Asm(), indent_level);
+ break;
}
- m_of << ");\n";
- break; }
+ break;
case ::MIR::Statement::TAG_Assign: {
const auto& e = stmt.as_Assign();
DEBUG("- " << e.dst << " = " << e.src);
@@ -2815,6 +2753,121 @@ namespace {
}
m_of << " );\n";
}
+ void emit_asm_gcc(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement::Data_Asm& e, unsigned indent_level)
+ {
+ auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) };
+ struct H {
+ static bool has_flag(const ::std::vector<::std::string>& flags, const char* des) {
+ return ::std::find_if(flags.begin(), flags.end(), [des](const auto&x) {return x == des; }) != flags.end();
+ }
+ static const char* convert_reg(const char* r) {
+ if (::std::strcmp(r, "{eax}") == 0 || ::std::strcmp(r, "{rax}") == 0) {
+ return "a";
+ }
+ else {
+ return r;
+ }
+ }
+ };
+ bool is_volatile = H::has_flag(e.flags, "volatile");
+ bool is_intel = H::has_flag(e.flags, "intel");
+
+
+ m_of << indent << "__asm__ ";
+ if (is_volatile) m_of << "__volatile__";
+ // TODO: Convert format string?
+ // TODO: Use a C-specific escaper here.
+ m_of << "(\"" << (is_intel ? ".syntax intel; " : "");
+ for (auto it = e.tpl.begin(); it != e.tpl.end(); ++it)
+ {
+ if (*it == '\n')
+ m_of << ";\\n";
+ else if (*it == '"')
+ m_of << "\\\"";
+ else if (*it == '\\')
+ m_of << "\\\\";
+ else if (*it == '/' && *(it + 1) == '/')
+ {
+ while (it != e.tpl.end() || *it == '\n')
+ ++it;
+ --it;
+ }
+ else if (*it == '%' && *(it + 1) == '%')
+ m_of << "%";
+ else if (*it == '%' && !isdigit(*(it + 1)))
+ m_of << "%%";
+ else
+ m_of << *it;
+ }
+ m_of << (is_intel ? ".syntax att; " : "") << "\"";
+ m_of << ": ";
+ for (unsigned int i = 0; i < e.outputs.size(); i++)
+ {
+ const auto& v = e.outputs[i];
+ if (i != 0) m_of << ", ";
+ m_of << "\"";
+ switch (v.first[0])
+ {
+ case '=': m_of << "="; break;
+ case '+': m_of << "+"; break;
+ default: MIR_TODO(mir_res, "Handle asm! output leader '" << v.first[0] << "'");
+ }
+ m_of << H::convert_reg(v.first.c_str() + 1);
+ m_of << "\"("; emit_lvalue(v.second); m_of << ")";
+ }
+ m_of << ": ";
+ for (unsigned int i = 0; i < e.inputs.size(); i++)
+ {
+ const auto& v = e.inputs[i];
+ if (i != 0) m_of << ", ";
+ m_of << "\"" << v.first << "\"("; emit_lvalue(v.second); m_of << ")";
+ }
+ m_of << ": ";
+ for (unsigned int i = 0; i < e.clobbers.size(); i++)
+ {
+ if (i != 0) m_of << ", ";
+ m_of << "\"" << e.clobbers[i] << "\"";
+ }
+ m_of << ");\n";
+ }
+ void emit_asm_msvc(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement::Data_Asm& e, unsigned indent_level)
+ {
+ auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) };
+
+ if( !e.inputs.empty() || !e.outputs.empty() )
+ {
+ MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly");
+#if 0
+ m_of << indent << "{\n";
+ for(size_t i = 0; i < e.inputs.size(); i ++)
+ {
+ m_of << indent << "auto asm_i_" << i << " = ";
+ emit_lvalue(e.inputs[i]);
+ }
+#endif
+ }
+
+ m_of << indent << "__asm {\n";
+
+ m_of << indent << "\t";
+ for (auto it = e.tpl.begin(); it != e.tpl.end(); ++it)
+ {
+ if (*it == ';')
+ {
+ m_of << "\n";
+ m_of << indent << "\t";
+ }
+ else
+ m_of << *it;
+ }
+
+ m_of << "\n" << indent << "}";
+ if (!e.inputs.empty() || !e.outputs.empty())
+ {
+ m_of << "}";
+ }
+ m_of << ";\n";
+ }
private:
const ::HIR::TypeRef& monomorphise_fcn_return(::HIR::TypeRef& tmp, const ::HIR::Function& item, const Trans_Params& params)
{
@@ -2960,6 +3013,7 @@ namespace {
m_of << ", "<<o_succ<<", "<<o_fail<<")";
break;
case Compiler::Msvc:
+ emit_lvalue(e.ret_val); m_of << "._0 = ";
emit_msvc_atomic_op("InterlockedCompareExchange", ""); // TODO: Use ordering
if(params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize)
{
@@ -2969,6 +3023,8 @@ namespace {
{
emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", "; emit_param(e.args.at(2)); m_of << ")";
}
+ m_of << ";\n\t";
+ emit_lvalue(e.ret_val); m_of << "._1 = ("; emit_lvalue(e.ret_val); m_of << "._0 == "; emit_param(e.args.at(2)); m_of << ")";
break;
}
};
@@ -3349,7 +3405,16 @@ namespace {
{
m_of << "shl128";
if(params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
- m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", ";
+ emit_param(e.args.at(1));
+ // If the shift type is a u128/i128, get the inner
+ ::HIR::TypeRef tmp;
+ const auto& shift_ty = mir_res.get_param_type(tmp, e.args.at(1));
+ if( shift_ty == ::HIR::CoreType::I128 || shift_ty == ::HIR::CoreType::U128 )
+ {
+ m_of << ".lo";
+ }
+ m_of << ")";
}
else
{
@@ -3362,7 +3427,16 @@ namespace {
{
m_of << "shr128";
if (params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
- m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", ";
+ emit_param(e.args.at(1));
+ // If the shift type is a u128/i128, get the inner
+ ::HIR::TypeRef tmp;
+ const auto& shift_ty = mir_res.get_param_type(tmp, e.args.at(1));
+ if( shift_ty == ::HIR::CoreType::I128 || shift_ty == ::HIR::CoreType::U128 )
+ {
+ m_of << ".lo";
+ }
+ m_of << ")";
}
else
{
@@ -4154,13 +4228,21 @@ namespace {
m_of << "\", " << ::std::dec << c.size() << ")";
),
(Const,
- // TODO: This should have been eliminated?
- // NOTE: GCC hack - statement expressions
+ // TODO: This should have been eliminated? ("MIR Cleanup" should have removed all inline Const references)
::HIR::TypeRef ty;
const auto& lit = get_literal_for_const(c.p, ty);
- m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; ";
- assign_from_literal([&](){ m_of << "v"; }, ty, lit);
- m_of << "; v;})";
+ if(lit.is_Integer() || lit.is_Float() || lit.is_String())
+ {
+ emit_literal(ty, lit, {});
+ }
+ else
+ {
+ // NOTE: GCC hack - statement expressions
+ MIR_ASSERT(*m_mir_res, m_compiler == Compiler::Gcc, "TODO: Support inline constants without statement expressions");
+ m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; ";
+ assign_from_literal([&](){ m_of << "v"; }, ty, lit);
+ m_of << "; v;})";
+ }
),
(ItemAddr,
TU_MATCHA( (c.m_data), (pe),