summary refs log tree commit diff stats
path: root/compiler/tccgen.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/tccgen.nim')
-rw-r--r--compiler/tccgen.nim89
1 files changed, 89 insertions, 0 deletions
diff --git a/compiler/tccgen.nim b/compiler/tccgen.nim
new file mode 100644
index 000000000..9ee8516c4
--- /dev/null
+++ b/compiler/tccgen.nim
@@ -0,0 +1,89 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2012 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+import
+  os, strutils, options, msgs, tinyc, lineinfos, sequtils
+
+const tinyPrefix = "dist/nim-tinyc-archive".unixToNativePath
+const nimRoot = currentSourcePath.parentDir.parentDir
+const tinycRoot = nimRoot / tinyPrefix
+when not dirExists(tinycRoot):
+  static: raiseAssert $(tinycRoot, "requires: ./koch installdeps tinyc")
+{.compile: tinycRoot / "tinyc/libtcc.c".}
+
+var
+  gConf: ConfigRef # ugly but can be cleaned up if this is revived
+
+proc tinyCErrorHandler(closure: pointer, msg: cstring) {.cdecl.} =
+  rawMessage(gConf, errGenerated, $msg)
+
+proc initTinyCState: PccState =
+  result = openCCState()
+  setErrorFunc(result, nil, tinyCErrorHandler)
+
+var
+  gTinyC = initTinyCState()
+  libIncluded = false
+
+proc addFile(filename: string) =
+  if addFile(gTinyC, filename) != 0'i32:
+    rawMessage(gConf, errCannotOpenFile, filename)
+
+proc setupEnvironment =
+  when defined(amd64):
+    defineSymbol(gTinyC, "__x86_64__", nil)
+  elif defined(i386):
+    defineSymbol(gTinyC, "__i386__", nil)
+  when defined(linux):
+    defineSymbol(gTinyC, "__linux__", nil)
+    defineSymbol(gTinyC, "__linux", nil)
+
+  var nimDir = getPrefixDir(gConf).string
+  var tinycRoot = nimDir / tinyPrefix
+  let libpath = nimDir / "lib"
+
+  addIncludePath(gTinyC, cstring(libpath))
+  when defined(windows):
+    addSysincludePath(gTinyC, cstring(tinycRoot / "tinyc/win32/include"))
+  addSysincludePath(gTinyC, cstring(tinycRoot / "tinyc/include"))
+  when defined(windows):
+    defineSymbol(gTinyC, "_WIN32", nil)
+    # we need Mingw's headers too:
+    var gccbin = getConfigVar("gcc.path") % ["nim", tinycRoot]
+    addSysincludePath(gTinyC, cstring(gccbin /../ "include"))
+    #addFile(tinycRoot / r"tinyc\win32\wincrt1.o")
+    addFile(tinycRoot / r"tinyc\win32\alloca86.o")
+    addFile(tinycRoot / r"tinyc\win32\chkstk.o")
+    #addFile(tinycRoot / r"tinyc\win32\crt1.o")
+
+    #addFile(tinycRoot / r"tinyc\win32\dllcrt1.o")
+    #addFile(tinycRoot / r"tinyc\win32\dllmain.o")
+    addFile(tinycRoot / r"tinyc\win32\libtcc1.o")
+
+    #addFile(tinycRoot / r"tinyc\win32\lib\crt1.c")
+    #addFile(tinycRoot / r"tinyc\lib\libtcc1.c")
+  else:
+    addSysincludePath(gTinyC, "/usr/include")
+    when defined(amd64):
+      addSysincludePath(gTinyC, "/usr/include/x86_64-linux-gnu")
+
+proc compileCCode*(ccode: string, conf: ConfigRef) =
+  gConf = conf
+  if not libIncluded:
+    libIncluded = true
+    setupEnvironment()
+  discard compileString(gTinyC, ccode)
+
+proc run*(conf: ConfigRef, args: string) =
+  doAssert gConf == conf
+  var s = @[cstring(conf.projectName)] & map(split(args), proc(x: string): cstring = cstring(x))
+  var err = tinyc.run(gTinyC, cint(s.len), cast[cstringArray](addr(s[0]))) != 0'i32
+  closeCCState(gTinyC)
+  if err: rawMessage(conf, errUnknown, "")
+