@@ -44,6 +44,7 @@ abstract class GenLLVM extends SubComponent {
44
44
val LlvmdefsAnnotSym = definitions.getClass(" scala.llvmdefs" )
45
45
val ForeignAnnotSym = definitions.getClass(" scala.ffi.foreign" )
46
46
val ForeignValueAnnotSym = definitions.getClass(" scala.ffi.foreignValue" )
47
+ val ForeignExportAnnotSym = definitions.getClass(" scala.ffi.foreignExport" )
47
48
val CodegenAnnotations = Set (LlvmimplAnnotSym , ForeignAnnotSym , ForeignValueAnnotSym )
48
49
val PtrSym = definitions.getClass(" scala.ffi.Ptr" )
49
50
val PtrObjSym = PtrSym .companionModule
@@ -732,6 +733,47 @@ abstract class GenLLVM extends SubComponent {
732
733
}
733
734
}
734
735
736
+ def exportFunction (m : IMethod ): Seq [ModuleComp ] = {
737
+ m.symbol.getAnnotation(ForeignExportAnnotSym ) match {
738
+ case Some (AnnotationInfo (_,List (Literal (Constant (foreignSymbol : String ))),_)) => {
739
+ val methType = m.symbol.info
740
+ if (! m.symbol.isStatic) {
741
+ error(" Only object methods can be exported" ); Seq .empty
742
+ } else if (methType.paramSectionCount != 1 ) {
743
+ error(" Exported functions must take exactly one parameter list" ); Seq .empty
744
+ } else if (! isMarshallableResult(methType.resultType)) {
745
+ error(" Exported functions must have marshallable return type" ); Seq .empty
746
+ } else if (methType.paramTypes.exists(pt => ! isMarshallable(pt))) {
747
+ error(" All parameters to exported functions must be marshallable" ); Seq .empty
748
+ } else {
749
+ val args = m.params.map(p => new LocalVariable (llvmName(p.sym), marshalledType(p.sym.info)))
750
+ val argSpec = args.map(lv => ArgSpec (lv))
751
+ val exportedFun = new LMFunction (
752
+ typeKindType(m.returnType), foreignSymbol, argSpec, false ,
753
+ Externally_visible , Default , Ccc ,
754
+ Seq .empty, Seq .empty, None , None , None )
755
+ val methodFun = functionForMethod(m)._1
756
+ val modGlobal = new CGlobalAddress (externModule(m.symbol.enclClass))
757
+ val body = if (m.returnType == UNIT ) {
758
+ Seq (
759
+ new call_void(moduleInitFun(m.symbol.owner), Seq .empty),
760
+ new call_void(methodFun, Seq (modGlobal) ++ args),
761
+ retvoid
762
+ )
763
+ } else {
764
+ val result = new LocalVariable (" .result" , typeKindType(m.returnType))
765
+ Seq (
766
+ new call_void(moduleInitFun(m.symbol.owner), Seq .empty),
767
+ new call(result, methodFun, Seq (modGlobal) ++ args),
768
+ new ret(result)
769
+ )
770
+ }
771
+ Seq (exportedFun.define(Seq (LMBlock (None , body))))
772
+ }
773
+ }
774
+ }
775
+ }
776
+
735
777
def genForeignFun (m : IMethod ): Seq [ModuleComp ] = {
736
778
m.symbol.getAnnotation(ForeignAnnotSym ) match {
737
779
case Some (AnnotationInfo (_,List (Literal (Constant (foreignSymbol : String ))),_)) => {
@@ -1716,6 +1758,7 @@ abstract class GenLLVM extends SubComponent {
1716
1758
c.methods.filter(_.native).map(_.symbol).foreach(externFun)
1717
1759
val externDecls = externFuns.filterKeys(! internalFuns.contains(_)).values.map(_.declare)++ externClasses.values.map(_.declare)++ externStatics.values.map(_.declare)
1718
1760
val otherModules = externModules.filterKeys(_.moduleClass!= c.symbol)
1761
+ val exportedFunctions = c.methods.filter(_.symbol.hasAnnotation(ForeignExportAnnotSym )).flatMap(exportFunction)
1719
1762
val module = new Module (Seq .concat(
1720
1763
Seq (header_comment),
1721
1764
externTypes.values.map {
@@ -1729,6 +1772,7 @@ abstract class GenLLVM extends SubComponent {
1729
1772
classInfo,
1730
1773
methodFuns,
1731
1774
llvmmethodFuns,
1775
+ exportedFunctions,
1732
1776
foreignFuns,
1733
1777
foreignVals,
1734
1778
extraDefs,
0 commit comments