-- filter to get only dataTyCons?
ilxTyConDef importing env tycon =
vcat [empty $$ line,
- text ".classunion" <+> (if importing then text "import" else empty) <+> tyvars_text <+> text ": thunk"
- <> angleBrackets((nameReference env (getName tycon)) <> (ppr tycon)) <+> alts_text]
+ text ".classunion" <+> (if importing then text "import" else empty) <+> tycon_ref <+> tyvars_text <+> super_text <+> alts_text]
where
+ tycon_ref = nameReference env (getName tycon) <> (ppr tycon)
+ super_text = if importing then empty else text "extends thunk" <> angleBrackets (text "class" <+> tycon_ref)
tyvars = tyConTyVars tycon
(ilx_tvs, _) = categorizeTyVars tyvars
alts_env = extendIlxEnvWithFormalTyVars env ilx_tvs
-- ldloc x arg of type Int
-- .tail callfunc <Int32> (!0) --> !0
--
- vcat [pushId env fun,ilxFunAppArgs env 0 (idIlxRepType fun) args tail_call known_clo]
+ vcat [pushId env fun,ilxFunAppAfterPush env fun args tail_call]
+
+ilxFunAppAfterPush env fun args tail_call
+ = -- For example:
+ -- ldloc f function of type forall a. a->a
+ -- ldloc x arg of type Int
+ -- .tail callfunc <Int32> (!0) --> !0
+ --
+ vcat [ilxFunAppArgs env 0 (idIlxRepType fun) args tail_call known_clo]
where
known_clo :: KnownClosure
known_clo =
Just rep_ty ->
let res = deepIlxRepType (applyTys rep_ty tys) in
if not (length tys == tyConArity tc ) then
- pprTrace "deepIlxRepType" (text "length tys <> tyConArity tc, ty = " <+> pprType ty <+> text ", length tys = " <+> ppr (length tys) <+> text ", tyConArity = " <+> ppr (tyConArity tc)) res
+ --pprTrace "deepIlxRepType" (text "length tys <> tyConArity tc, ty = " <+> pprType ty <+> text ", length tys = " <+> ppr (length tys) <+> text ", tyConArity = " <+> ppr (tyConArity tc))
+ res
else res
- -- The assert should hold because deepIlxRepType should
- -- only be applied to *types* (of kind *)
Nothing ->
-- collapse UnboxedTupleTyCon down when it contains VoidRep types.
-- e.g. (# State#, Int#, Int# #) ===> (# Int#, Int# #)
ilxFCall env (DNCall (DNCallSpec call_instr)) args ret_ty
= ilxComment (text "IL call") <+>
- vcat [vcat (ilxMapPlaceArgs 0 pushILArg env tm_args),
+ vcat [vcat (ilxMapPlaceArgs 0 pushEvalArg env tm_args),
ptext call_instr
-- In due course we'll need to pass the type arguments
-- and to do that we'll need to have more than just a string
where
(ty_args,tm_args) = splitTyArgs1 args
-pushILArg env arg | isUnLiftedType (stgArgType arg) = pushArg env arg
- | otherwise = pushArg env arg <+> text "EVAL!"
+-- Push and argument and force its evaluation if necessary.
+pushEvalArg _ (StgTypeArg _) = empty
+pushEvalArg env (StgVarArg arg) = ilxFunApp env arg [] False
+pushEvalArg env (StgLitArg lit) = pushLit env lit
+
hasTyCon (TyConApp tc _) tc2 = tc == tc2
hasTyCon _ _ = False
| otherwise -- Normal foreign import
= checkCg (if isCasmTarget target
- then checkC else checkCOrAsm) `thenNF_Tc_`
+ then checkC else checkCOrAsmOrDotNet) `thenNF_Tc_`
checkCTarget target `thenNF_Tc_`
getDOptsTc `thenNF_Tc` \ dflags ->
checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys `thenNF_Tc_`
-- This makes a convenient place to check
-- that the C identifier is valid for C
checkCTarget (StaticTarget str)
- = checkCg checkCOrAsm `thenNF_Tc_`
+ = checkCg checkCOrAsmOrDotNet `thenNF_Tc_`
check (isCLabelString str) (badCName str)
checkCTarget (CasmTarget _)
checkCOrAsm HscAsm = Nothing
checkCOrAsm other = Just (text "via-C or native code generation (-fvia-C)")
+checkCOrAsmOrDotNet HscC = Nothing
+checkCOrAsmOrDotNet HscAsm = Nothing
+checkCOrAsmOrDotNet HscILX = Nothing
+checkCOrAsmOrDotNet other = Just (text "requires C, native or .NET ILX code generation")
+
checkCg check
= getDOptsTc `thenNF_Tc` \ dflags ->
case check (dopt_HscLang dflags) of