X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fcmm%2FPprC.hs;h=a0661cdd529263883342076c6ad6f84c7bc6d152;hp=9a3a3a2cf17eaed804e59dbbaea6283d19c48166;hb=bca74f3e6bde807d688e39e6de28112ebcb4fa49;hpb=dcf739bd7fb7de140be3bafb4ce211e2e5c7bba9 diff --git a/compiler/cmm/PprC.hs b/compiler/cmm/PprC.hs index 9a3a3a2..a0661cd 100644 --- a/compiler/cmm/PprC.hs +++ b/compiler/cmm/PprC.hs @@ -203,25 +203,44 @@ pprStmt stmt = case stmt of where rep = cmmExprRep src - CmmCall (CmmCallee fn cconv) results args safety _ret -> + CmmCall (CmmCallee fn cconv) results args safety ret -> maybe_proto $$ pprCall ppr_fn cconv results args safety where - ppr_fn = parens (cCast (pprCFunType (char '*') cconv results args) fn) + cast_fn = parens (cCast (pprCFunType (char '*') cconv results args) fn) + + real_fun_proto lbl = char ';' <> + pprCFunType (pprCLabel lbl) cconv results args <> + noreturn_attr <> semi + + data_proto lbl = ptext (sLit ";EI_(") <> + pprCLabel lbl <> char ')' <> semi + + noreturn_attr = case ret of + CmmNeverReturns -> text "__attribute__ ((noreturn))" + CmmMayReturn -> empty -- See wiki:Commentary/Compiler/Backends/PprC#Prototypes - maybe_proto = + (maybe_proto, ppr_fn) = case fn of - CmmLit (CmmLabel lbl) | not (isMathFun lbl) -> - ptext (sLit ";EI_(") <+> pprCLabel lbl <> char ')' <> semi - -- we declare all called functions as data labels, - -- and then cast them to the right type when calling. - -- This is because the label might already have a - -- declaration as a data label in the same file, - -- e.g. Foreign.Marshal.Alloc declares 'free' as - -- both a data label and a function label. + CmmLit (CmmLabel lbl) + | StdCallConv <- cconv -> (real_fun_proto lbl, pprCLabel lbl) + -- stdcall functions must be declared with + -- a function type, otherwise the C compiler + -- doesn't add the @n suffix to the label. We + -- can't add the @n suffix ourselves, because + -- it isn't valid C. + | CmmNeverReturns <- ret -> (real_fun_proto lbl, pprCLabel lbl) + | not (isMathFun lbl) -> (data_proto lbl, cast_fn) + -- we declare all other called functions as + -- data labels, and then cast them to the + -- right type when calling. This is because + -- the label might already have a declaration + -- as a data label in the same file, + -- e.g. Foreign.Marshal.Alloc declares 'free' + -- as both a data label and a function label. _ -> - empty {- no proto -} + (empty {- no proto -}, cast_fn) -- for a dynamic call, no declaration is necessary. CmmCall (CmmPrim op) results args safety _ret -> @@ -809,7 +828,8 @@ pprExternDecl :: Bool -> CLabel -> SDoc pprExternDecl in_srt lbl -- do not print anything for "known external" things | not (needsCDecl lbl) = empty - | otherwise = + | Just sz <- foreignLabelStdcallInfo lbl = stdcall_decl sz + | otherwise = hcat [ visibility, label_type (labelType lbl), lparen, pprCLabel lbl, text ");" ] where @@ -820,6 +840,13 @@ pprExternDecl in_srt lbl | externallyVisibleCLabel lbl = char 'E' | otherwise = char 'I' + -- If the label we want to refer to is a stdcall function (on Windows) then + -- we must generate an appropriate prototype for it, so that the C compiler will + -- add the @n suffix to the label (#2276) + stdcall_decl sz = + ptext (sLit "extern __attribute__((stdcall)) void ") <> pprCLabel lbl + <> parens (commafy (replicate (sz `quot` wORD_SIZE) (machRepCType wordRep))) + <> semi type TEState = (UniqSet LocalReg, FiniteMap CLabel ()) newtype TE a = TE { unTE :: TEState -> (a, TEState) }