' Gambas module file

Export
Class __Jit

Property Read Time As Float

Private $fTime As Float
Private $sCompiler As String
Private $aFlags As String[]
Private $hProcess As Process
Private $sResult As String
Private $bDebug As Integer

Private Sub Init()

  Dim sFlag As String
  Dim sCompiler As String
  
  sCompiler = Env["GB_JIT_CC"]
  If Not sCompiler Then sCompiler = "gcc"
  
  $sCompiler = System.Find(sCompiler)
  If Not $sCompiler Then Error.Raise("Compiler not found")

  sFlag = Env["GB_JIT_CFLAGS"] 
  If Not sFlag Then sFlag = "-O3"
  
  $aFlags = Split(sFlag, " ")
   
End

Private Sub RunCompiler(sInput As String, Optional sOutput As String, sOption As String) As String

  Dim aExec As String[]
  'Dim I As Integer
  
  aExec = [$sCompiler]
  If sOption Then aExec.Insert(Split(sOption, " "))
  aExec.Insert($aFlags)
  aExec.Add(sInput)
  If sOutput Then 
    aExec.Add("-o")
    aExec.Add(sOutput)
  Endif
  
  ' For I = 0 To aExec.Max
  '   aExec[I] = Shell$(aExec[I])
  ' Next
  
  If $bDebug Then Error "gb.jit: run: "; aExec.Join(" ")
  
  $sResult = ""
  $hProcess = Exec aExec For Read As "Compiler"
  $hProcess.Wait
  'Shell aExec.Join(" ") & " 2>&1" To sResult
  
  Return $sResult
  
End

Public Sub Compiler_Read()

  Dim sData As String
  
  sData = Read #$hProcess, -1024
  $sResult &= sData
  
End

Public Sub Compile_Error(({Error}) As String)
  
  $sResult &= {Error}
  
End

Public Sub _Compile(sArch As String) As String

  Dim sFile As String
  Dim sDir As String
  Dim sName As String
  Dim sPath As String
  Dim hFile As File
  Dim sResult As String
  Dim sPathO As String
  Dim sPathSO As String
  Dim fTime As Float
  
  fTime = Timer
  
  Try $bDebug = CInt(Env["GB_JIT_DEBUG"])
  
  If $bDebug Then Error "gb.jit: translating "; If(sArch, sArch, "project")
  
  If Not $sCompiler Then Init
  
  
  sName = sArch
  If Not sName Then sName = "gb"
  
  sDir = File.Dir(Temp$()) &/ "jit"
  Try Mkdir sDir
  
  sPath = sDir &/ "jit.h"
  
  If Not Exist(sPath) Then
    
    If $bDebug Then Error "gb.jit: generating header"
    
    hFile = Open sPath For Output Create
    
    Print #hFile, "#define NO_CONFIG_H"
    
    Print #hFile, File.Load("gambas.h");
    Print #hFile, File.Load("jit.h");
    Print #hFile, File.Load("gb.jit.h");

    Print #hFile, "GB_INTERFACE * GB_PTR;"
    Print #hFile, "#define GB (*GB_PTR)"
    Print #hFile, "JIT_INTERFACE * JIT_PTR;"
    Print #hFile, "#define JIT (*JIT_PTR)"
    
    Print #hFile, File.Load("gb_error_common.h");
    
    Close #hFile
    
    If $bDebug Then
      Try Kill "/tmp/jit.h"
      Copy sDir &/ "jit.h" To "/tmp/jit.h"
    Endif
    
    ' 'Shell $sCompiler & " -fPIC " & Shell(sPath) To sResult
    ' sResult = RunCompiler(sPath,, "-fPIC")
    ' If Not Exist(sPath & ".gch") Then
    '   Error "gb.jit: error: unable to generate precompiled header"
    '   Error sResult
    '   Return
    ' Endif
    ' 
    ' If $bDebug Then 
    '   Try Kill "/tmp/" & File.Name(sPath)
    '   Copy sPath To "/tmp/" & File.Name(sPath)
    '   Try Kill "/tmp/" & File.Name(sPath & ".gch")
    '   Copy sPath & ".gch" To "/tmp/" & File.Name(sPath & ".gch")
    ' Endif
    
  Endif
  
  sPath = sDir &/ sName & ".c"

  If $bDebug Then Error "gb.jit: generating "; sPath
  
  hFile = Open sPath For Output Create
  
  Print #hFile, "#include \"jit.h\""
  Print #hFile

  If sArch Then
    sDir = "." &/ sArch
  Else
    sDir = "..."
  Endif
  
  For Each sFile In Dir(sDir &/ ".gambas")
    _ClassStat.Stat(sDir, sFile)
    If Not _ClassStat.HasFast Then Continue 
    sFile = _ClassStat.Name
    If $bDebug Then Error "gb.jit: translating class "; sFile
    Print #hFile, __Jit.Translate(sFile, sArch)
  Next
  
  Close #hFile
  
  If $bDebug Then 
    Try Kill "/tmp/" & File.Name(sPath)
    Copy sPath To "/tmp/" & File.Name(sPath)
  Endif
  
  sPathO = File.SetExt(sPath, "o")
  sPathSO = File.SetExt(sPath, "so")
  
  If $bDebug Then Error "gb.jit: compiling to "; sPathO
  
  'gcc -c -fPIC -o foo.o foo.c
  'Exec [$sCompiler, "-c", "-fPIC", "-o", File.SetExt(sPath, "o"), sPath] To sResult
  'Shell $sCompiler & " -c -fPIC " & sFlag & " -o " & Shell(sPathO) & " " & Shell(sPath) & " 2>&1" To sResult
  sResult = RunCompiler(sPath, sPathSO, "-w -fPIC -shared -lm")
  If Not Exist(sPathSO) Then 
    Error "gb.jit: error: unable to compile JIT code:"
    Error sResult
    Return
  Endif

  ' If $bDebug Then Error "gb.jit: linking to "; sPathSO
  ' 
  ' 'gcc -shared -o libfoo.so foo.o
  ' 'Exec [$sCompiler, "-shared", "-o", File.SetExt(sPath, "so"), File.SetExt(sPath, "o")] To sResult
  ' 'Shell $sCompiler & " -shared " & sFlag & " -lm -o " & Shell(sPathSO) & " " & Shell(sPathO) & " 2>&1" To sResult
  ' RunCompiler(sPathO, sPathSO, "-shared -lm")
  ' If Not Exist(sPathSO) Then 
  '   Error "gb.jit: warning: unable to link JIT code:"
  '   Error sResult
  '   Return
  ' Endif
  
  fTime = Timer - fTime
  $fTime += fTime
  
  If $bDebug Then Error "gb.jit: done in "; Format(fTime, "0.000"); "s"
  
  ' Shell "objdump -S " & Shell(sPathSO) To sResult
  ' Error sResult
  
  Return sPathSO
  
End

Private Function Time_Read() As Float

  Return $fTime

End