summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expand/asm.cpp42
-rw-r--r--src/hir_typeck/helpers.cpp2
-rw-r--r--src/main.cpp2
-rw-r--r--src/mir/from_hir.cpp10
-rw-r--r--src/trans/codegen_c.cpp90
-rw-r--r--src/trans/target.cpp20
6 files changed, 143 insertions, 23 deletions
diff --git a/src/expand/asm.cpp b/src/expand/asm.cpp
index 6ca90f3e..336321f7 100644
--- a/src/expand/asm.cpp
+++ b/src/expand/asm.cpp
@@ -49,9 +49,12 @@ class CAsmExpander:
::std::vector<::std::string> flags;
// Outputs
- if( lex.lookahead(0) == TOK_COLON )
+ if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON )
{
GET_TOK(tok, lex);
+ if( tok.type() == TOK_DOUBLE_COLON ) {
+ lex.putback(Token(TOK_COLON));
+ }
while( lex.lookahead(0) == TOK_STRING )
{
@@ -73,9 +76,12 @@ class CAsmExpander:
}
// Inputs
- if( lex.lookahead(0) == TOK_COLON )
+ if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON )
{
GET_TOK(tok, lex);
+ if( tok.type() == TOK_DOUBLE_COLON ) {
+ lex.putback(Token(TOK_COLON));
+ }
while( lex.lookahead(0) == TOK_STRING )
{
@@ -95,9 +101,12 @@ class CAsmExpander:
}
// Clobbers
- if( lex.lookahead(0) == TOK_COLON )
+ if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON )
{
GET_TOK(tok, lex);
+ if( tok.type() == TOK_DOUBLE_COLON ) {
+ lex.putback(Token(TOK_COLON));
+ }
while( lex.lookahead(0) == TOK_STRING )
{
@@ -111,9 +120,12 @@ class CAsmExpander:
}
// Flags
- if( lex.lookahead(0) == TOK_COLON )
+ if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON )
{
GET_TOK(tok, lex);
+ if( tok.type() == TOK_DOUBLE_COLON ) {
+ lex.putback(Token(TOK_COLON));
+ }
while( lex.lookahead(0) == TOK_STRING )
{
@@ -126,6 +138,28 @@ class CAsmExpander:
}
}
+ if( lex.lookahead(0) == TOK_COLON || lex.lookahead(0) == TOK_DOUBLE_COLON )
+ {
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_DOUBLE_COLON ) {
+ lex.putback(Token(TOK_COLON));
+ }
+
+ if( GET_TOK(tok, lex) == TOK_IDENT && tok.str() == "volatile" )
+ {
+ flags.push_back( "volatile" );
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ }
+ }
+
+ if( lex.lookahead(0) != TOK_EOF )
+ {
+ ERROR(sp, E0000, "Unexpected token in asm! - " << lex.getToken());
+ }
+
::AST::ExprNodeP rv = ::AST::ExprNodeP( new ::AST::ExprNode_Asm { mv$(template_text), mv$(outputs), mv$(inputs), mv$(clobbers), mv$(flags) } );
// TODO: Convert this into an AST node
return box$( TTStreamO(TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, rv.release()) ))));
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 94f7304d..0c8b87c5 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -2826,7 +2826,6 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
auto rv = this->find_trait_impls(sp, real_trait_path.m_path, real_trait_path.m_params, real_type, [&](auto impl, auto impl_cmp) {
DEBUG("[ftic_check_params] impl_cmp = " << impl_cmp << ", impl = " << impl);
auto cmp = impl_cmp;
-#if 1
if( cmp == ::HIR::Compare::Fuzzy )
{
// If the match was fuzzy, try again filling in with `cb_match`
@@ -2841,7 +2840,6 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
cmp &= real_trait_path.m_params .match_test_generics_fuzz(sp, i_tp, cb_infer, cb_match);
DEBUG("[ftic_check_params] - Re-check result: " << cmp);
}
-#endif
for(const auto& assoc_bound : real_trait.m_type_bounds) {
::HIR::TypeRef tmp;
const ::HIR::TypeRef* ty_p;
diff --git a/src/main.cpp b/src/main.cpp
index d2330568..c159ca4b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -29,7 +29,7 @@
// Hacky default target
#ifdef _MSC_VER
-#define DEFAULT_TARGET_NAME "x86_64-windows-msvc"
+#define DEFAULT_TARGET_NAME "x86-windows-msvc"
#elif defined(__GNU__)
# if defined(__linux__)
#define DEFAULT_TARGET_NAME "x86_64-linux-gnu"
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 7773a81c..8ea22cef 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -506,6 +506,7 @@ namespace {
TRACE_FUNCTION_F("_Asm");
::std::vector< ::std::pair< ::std::string, ::MIR::LValue> > inputs;
+ // Inputs just need to be in lvalues
for(auto& v : node.m_inputs) {
this->visit_node_ptr(v.value);
auto lv = m_builder.get_result_in_lvalue(v.value->span(), v.value->m_res_type);
@@ -513,9 +514,16 @@ namespace {
}
::std::vector< ::std::pair< ::std::string, ::MIR::LValue> > outputs;
+ // Outputs can also (sometimes) be rvalues (only for `*m`?)
for(auto& v : node.m_outputs) {
this->visit_node_ptr(v.value);
- auto lv = m_builder.get_result_unwrap_lvalue(v.value->span());
+ if( v.spec[0] != '=' )
+ ERROR(node.span(), E0000, "Assembly output specifiers must start with =");
+ ::MIR::LValue lv;
+ if(v.spec[1] == '*')
+ lv = m_builder.get_result_in_lvalue(v.value->span(), v.value->m_res_type);
+ else
+ lv = m_builder.get_result_unwrap_lvalue(v.value->span());
outputs.push_back( ::std::make_pair(v.spec, mv$(lv)) );
}
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index b942dae7..1ec2d2cd 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -520,7 +520,10 @@ namespace {
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");
+ if( Target_GetCurSpec().m_arch.m_pointer_bits == 64 )
+ {
+ args.push_back("amd64"); // NOTE: Doesn't support inline assembly, only works with overrides
+ }
args.push_back("&");
args.push_back("cl.exe");
args.push_back("/nologo");
@@ -584,6 +587,10 @@ namespace {
cmd_ss << "&";
}
else {
+ if( is_windows && strchr(arg, ' ') == nullptr ) {
+ cmd_ss << arg << " ";
+ continue ;
+ }
cmd_ss << "\"" << FmtShell(arg, is_windows) << "\" ";
}
}
@@ -628,7 +635,15 @@ namespace {
void emit_type_id(const ::HIR::TypeRef& ty) override
{
- m_of << "tTYPEID __typeid_" << Trans_Mangle(ty) << " __attribute__((weak));\n";
+ switch(m_compiler)
+ {
+ case Compiler::Gcc:
+ m_of << "tTYPEID __typeid_" << Trans_Mangle(ty) << " __attribute__((weak));\n";
+ break;
+ case Compiler::Msvc:
+ m_of << "__declspec(selectany) tTYPEID __typeid_" << Trans_Mangle(ty) << ";\n";
+ break;
+ }
}
void emit_type_proto(const ::HIR::TypeRef& ty) override
{
@@ -673,7 +688,21 @@ namespace {
m_of << "typedef ";
// TODO: ABI marker, need an ABI enum?
// TODO: Better emit_ctype call for return type.
- emit_ctype(*te.m_rettype); m_of << " (*"; emit_ctype(ty); m_of << ")(";
+ emit_ctype(*te.m_rettype); m_of << " (";
+ if( m_compiler == Compiler::Msvc )
+ {
+ if( te.m_abi == ABI_RUST )
+ {
+ }
+ else if( te.m_abi == "system" )
+ {
+ m_of << "__stdcall";
+ }
+ else
+ {
+ }
+ }
+ m_of << "*"; emit_ctype(ty); m_of << ")(";
if( te.m_arg_types.size() == 0 )
{
m_of << "void)";
@@ -843,8 +872,16 @@ namespace {
::std::vector< ::std::pair<::HIR::Pattern,::HIR::TypeRef> > args;
if( item.m_markings.has_drop_impl ) {
+ // If the type is defined outside the current crate, define as static (to avoid conflicts when we define it)
if( p.m_path.m_crate_name != m_crate.m_crate_name )
- m_of << "static ";
+ {
+ if( item.m_params.m_types.size() > 0 ) {
+ m_of << "static ";
+ }
+ else {
+ m_of << "extern ";
+ }
+ }
m_of << "tUNIT " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "("; emit_ctype(struct_ty_ptr, FMT_CB(ss, ss << "rv";)); m_of << ");\n";
}
else if( m_resolve.is_type_owned_box(struct_ty) )
@@ -1433,6 +1470,8 @@ namespace {
m_of << " ";
emit_literal(get_inner_type(0, i), e[i], params);
}
+ if(ty.m_data.is_Path() && e.size() == 0 && m_options.disallow_empty_structs)
+ m_of << "0";
m_of << " }";
if( ty.m_data.is_Array() )
m_of << "}";
@@ -1460,25 +1499,25 @@ namespace {
}
else
{
- m_of << "{" << e.idx << ", { ";
+ m_of << "{" << e.idx;
if( e.vals.empty() )
{
if( m_options.disallow_empty_structs && !enm.m_variants.at(e.idx).second.is_Unit() )
{
- m_of << ".var_" << e.idx << " = {0} ";
+ m_of << ", { .var_" << e.idx << " = {0} }";
}
}
else
{
- m_of << ".var_" << e.idx << " = {";
+ m_of << ", { .var_" << e.idx << " = {";
for(unsigned int i = 0; i < e.vals.size(); i ++) {
if(i != 0) m_of << ",";
m_of << " ";
emit_literal(get_inner_type(e.idx, i), e.vals[i], params);
}
- m_of << "} ";
+ m_of << "} }";
}
- m_of << "}}";
+ m_of << "}";
}
),
(Integer,
@@ -1752,7 +1791,7 @@ namespace {
}
}
- m_of << "// extern \"" << item.m_abi << "\" " << p << "\n";
+ m_of << "// EXTERN extern \"" << item.m_abi << "\" " << p << "\n";
m_of << "extern ";
emit_function_header(p, item, params);
if( item.m_linkage.name != "" && m_compiler == Compiler::Gcc)
@@ -1769,6 +1808,7 @@ namespace {
m_mir_res = &top_mir_res;
TRACE_FUNCTION_F(p);
+ m_of << "// PROTO extern \"" << item.m_abi << "\" " << p << "\n";
if( item.m_linkage.name != "" )
{
m_of << "#define " << Trans_Mangle(p) << " " << item.m_linkage.name << "\n";
@@ -2942,9 +2982,37 @@ namespace {
{
auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) };
+ if( e.tpl == "fnstcw $0" )
+ {
+ // HARD CODE: `fnstcw` -> _control87
+ if( !(e.inputs.size() == 0 && e.outputs.size() == 1 && e.outputs[0].first == "=*m") )
+ MIR_BUG(mir_res, "Hard-coded asm translation doesn't apply - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs);
+ m_of << indent << "*("; emit_lvalue(e.outputs[0].second); m_of << ") = _control87(0,0);\n";
+ return ;
+ }
+ else if( e.tpl == "fldcw $0" )
+ {
+ // HARD CODE: `fldcw` -> _control87
+ if( !(e.inputs.size() == 1 && e.inputs[0].first == "m" && e.outputs.size() == 0) )
+ MIR_BUG(mir_res, "Hard-coded asm translation doesn't apply - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs);
+ m_of << indent << "_control87("; emit_lvalue(e.inputs[0].second); m_of << ", 0xFFFF);\n";
+ return ;
+ }
+ else if( e.tpl == "int $$0x29" )
+ {
+ if( !(e.inputs.size() == 1 && e.inputs[0].first == "{ecx}" && e.outputs.size() == 0) )
+ MIR_BUG(mir_res, "Hard-coded asm translation doesn't apply - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs);
+ m_of << indent << "__fastfail("; emit_lvalue(e.inputs[0].second); m_of << ");\n";
+ return ;
+ }
+ else
+ {
+ // No hard-coded translations.
+ }
+
if( !e.inputs.empty() || !e.outputs.empty() )
{
- MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly");
+ MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly - `" << e.tpl << "` inputs=" << e.inputs << " outputs=" << e.outputs);
#if 0
m_of << indent << "{\n";
for(size_t i = 0; i < e.inputs.size(); i ++)
diff --git a/src/trans/target.cpp b/src/trans/target.cpp
index d4f57107..bb0227fc 100644
--- a/src/trans/target.cpp
+++ b/src/trans/target.cpp
@@ -15,6 +15,11 @@ TargetArch ARCH_X86_64 = {
64, false,
{ /*atomic(u8)=*/true, false, true, true, true }
};
+TargetArch ARCH_X86 = {
+ "x86",
+ 32, false,
+ { /*atomic(u8)=*/true, false, true, false, true }
+};
TargetSpec g_target;
namespace
@@ -43,13 +48,20 @@ namespace
ARCH_X86_64
};
}
- else if (target_name == "x86_64-windows-msvc")
+ else if (target_name == "x86-windows-msvc")
{
return TargetSpec {
- "windows", "windows", "msvd", CodegenMode::Msvc,
- ARCH_X86_64
- };
+ "windows", "windows", "msvc", CodegenMode::Msvc,
+ ARCH_X86
+ };
}
+ //else if (target_name == "x86_64-windows-msvc")
+ //{
+ // return TargetSpec {
+ // "windows", "windows", "msvc", CodegenMode::Msvc,
+ // ARCH_X86_64
+ // };
+ //}
else
{
::std::cerr << "Unknown target name '" << target_name << "'" << ::std::endl;