lots of C++ codegen improvements
This commit is contained in:
parent
d020ad097c
commit
e84834db79
10 changed files with 71 additions and 119 deletions
|
|
@ -125,7 +125,7 @@ proc genArgStringToCString(p: BProc, n: PNode): PRope {.inline.} =
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
result = ropef("$1->data", [a.rdLoc])
|
result = ropef("$1->data", [a.rdLoc])
|
||||||
|
|
||||||
proc genArg(p: BProc, n: PNode, param: PSym): PRope =
|
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): PRope =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if n.kind == nkStringToCString:
|
if n.kind == nkStringToCString:
|
||||||
result = genArgStringToCString(p, n)
|
result = genArgStringToCString(p, n)
|
||||||
|
|
@ -138,6 +138,14 @@ proc genArg(p: BProc, n: PNode, param: PSym): PRope =
|
||||||
elif p.module.compileToCpp and param.typ.kind == tyVar and
|
elif p.module.compileToCpp and param.typ.kind == tyVar and
|
||||||
n.kind == nkHiddenAddr:
|
n.kind == nkHiddenAddr:
|
||||||
initLocExprSingleUse(p, n.sons[0], a)
|
initLocExprSingleUse(p, n.sons[0], a)
|
||||||
|
# if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
|
||||||
|
# means '*T'. See posix.nim for lots of examples that do that in the wild.
|
||||||
|
let callee = call.sons[0]
|
||||||
|
if callee.kind == nkSym and
|
||||||
|
{sfImportC, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportC} and
|
||||||
|
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {}:
|
||||||
|
result = addrLoc(a)
|
||||||
|
else:
|
||||||
result = rdLoc(a)
|
result = rdLoc(a)
|
||||||
else:
|
else:
|
||||||
initLocExprSingleUse(p, n, a)
|
initLocExprSingleUse(p, n, a)
|
||||||
|
|
@ -166,7 +174,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
if params != nil: app(params, ~", ")
|
if params != nil: app(params, ~", ")
|
||||||
if i < sonsLen(typ):
|
if i < sonsLen(typ):
|
||||||
assert(typ.n.sons[i].kind == nkSym)
|
assert(typ.n.sons[i].kind == nkSym)
|
||||||
app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym))
|
app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri))
|
||||||
else:
|
else:
|
||||||
app(params, genArgNoParam(p, ri.sons[i]))
|
app(params, genArgNoParam(p, ri.sons[i]))
|
||||||
fixupCall(p, le, ri, d, op.r, params)
|
fixupCall(p, le, ri, d, op.r, params)
|
||||||
|
|
@ -192,7 +200,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||||
if i < sonsLen(typ):
|
if i < sonsLen(typ):
|
||||||
assert(typ.n.sons[i].kind == nkSym)
|
assert(typ.n.sons[i].kind == nkSym)
|
||||||
app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym))
|
app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri))
|
||||||
else:
|
else:
|
||||||
app(pl, genArgNoParam(p, ri.sons[i]))
|
app(pl, genArgNoParam(p, ri.sons[i]))
|
||||||
if i < length - 1: app(pl, ~", ")
|
if i < length - 1: app(pl, ~", ")
|
||||||
|
|
@ -424,12 +432,12 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||||
|
|
||||||
if length > 1:
|
if length > 1:
|
||||||
app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym))
|
app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
|
||||||
app(pl, ~" ")
|
app(pl, ~" ")
|
||||||
app(pl, op.r)
|
app(pl, op.r)
|
||||||
if length > 2:
|
if length > 2:
|
||||||
app(pl, ~": ")
|
app(pl, ~": ")
|
||||||
app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym))
|
app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
|
||||||
for i in countup(3, length-1):
|
for i in countup(3, length-1):
|
||||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||||
if i >= sonsLen(typ):
|
if i >= sonsLen(typ):
|
||||||
|
|
@ -439,7 +447,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
app(pl, ~" ")
|
app(pl, ~" ")
|
||||||
app(pl, param.name.s)
|
app(pl, param.name.s)
|
||||||
app(pl, ~": ")
|
app(pl, ~": ")
|
||||||
app(pl, genArg(p, ri.sons[i], param))
|
app(pl, genArg(p, ri.sons[i], param, ri))
|
||||||
if typ.sons[0] != nil:
|
if typ.sons[0] != nil:
|
||||||
if isInvalidReturnType(typ.sons[0]):
|
if isInvalidReturnType(typ.sons[0]):
|
||||||
if sonsLen(ri) > 1: app(pl, ~" ")
|
if sonsLen(ri) > 1: app(pl, ~" ")
|
||||||
|
|
|
||||||
|
|
@ -682,7 +682,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
|
||||||
d.s = OnHeap
|
d.s = OnHeap
|
||||||
of tyVar:
|
of tyVar:
|
||||||
d.s = OnUnknown
|
d.s = OnUnknown
|
||||||
if p.module.compileToCpp:
|
if p.module.compileToCpp and e.kind == nkHiddenDeref:
|
||||||
putIntoDest(p, d, e.typ, rdLoc(a))
|
putIntoDest(p, d, e.typ, rdLoc(a))
|
||||||
return
|
return
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
|
|
@ -923,6 +923,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
L: TLabel
|
L: TLabel
|
||||||
tmp: TLoc
|
tmp: TLoc
|
||||||
getTemp(p, e.typ, tmp) # force it into a temp!
|
getTemp(p, e.typ, tmp) # force it into a temp!
|
||||||
|
inc p.splitDecls
|
||||||
expr(p, e.sons[1], tmp)
|
expr(p, e.sons[1], tmp)
|
||||||
L = getLabel(p)
|
L = getLabel(p)
|
||||||
if m == mOr:
|
if m == mOr:
|
||||||
|
|
@ -935,6 +936,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
d = tmp
|
d = tmp
|
||||||
else:
|
else:
|
||||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
|
dec p.splitDecls
|
||||||
|
|
||||||
proc genEcho(p: BProc, n: PNode) =
|
proc genEcho(p: BProc, n: PNode) =
|
||||||
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||||
registerGcRoot(p, v)
|
registerGcRoot(p, v)
|
||||||
else:
|
else:
|
||||||
let imm = isAssignedImmediately(a.sons[2])
|
let imm = isAssignedImmediately(a.sons[2])
|
||||||
if imm and p.module.compileToCpp:
|
if imm and p.module.compileToCpp and p.splitDecls == 0:
|
||||||
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
|
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
|
||||||
# parameterless constructor followed by an assignment operator. So we
|
# parameterless constructor followed by an assignment operator. So we
|
||||||
# generate better code here:
|
# generate better code here:
|
||||||
|
|
@ -286,17 +286,22 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||||
let it = n.sons[i]
|
let it = n.sons[i]
|
||||||
if it.len == 2:
|
if it.len == 2:
|
||||||
when newScopeForIf: startBlock(p)
|
when newScopeForIf: startBlock(p)
|
||||||
initLocExpr(p, it.sons[0], a)
|
initLocExprSingleUse(p, it.sons[0], a)
|
||||||
lelse = getLabel(p)
|
lelse = getLabel(p)
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
lineFF(p, cpsStmts, "if (!$1) goto $2;$n",
|
lineF(p, cpsStmts, "if (!$1) goto $2;$n",
|
||||||
"br i1 $1, label %LOC$3, label %$2$nLOC$3: $n",
|
[rdLoc(a), lelse])
|
||||||
[rdLoc(a), lelse, toRope(p.labels)])
|
|
||||||
when not newScopeForIf: startBlock(p)
|
when not newScopeForIf: startBlock(p)
|
||||||
|
if p.module.compileToCpp:
|
||||||
|
# avoid "jump to label crosses initialization" error:
|
||||||
|
app(p.s(cpsStmts), "{")
|
||||||
|
expr(p, it.sons[1], d)
|
||||||
|
app(p.s(cpsStmts), "}")
|
||||||
|
else:
|
||||||
expr(p, it.sons[1], d)
|
expr(p, it.sons[1], d)
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
if sonsLen(n) > 1:
|
if sonsLen(n) > 1:
|
||||||
lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [lend])
|
lineF(p, cpsStmts, "goto $1;$n", [lend])
|
||||||
fixLabel(p, lelse)
|
fixLabel(p, lelse)
|
||||||
elif it.len == 1:
|
elif it.len == 1:
|
||||||
startBlock(p)
|
startBlock(p)
|
||||||
|
|
@ -355,7 +360,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
||||||
# consume it before we return.
|
# consume it before we return.
|
||||||
var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
|
var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
|
||||||
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)
|
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)
|
||||||
lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", [])
|
lineF(p, cpsStmts, "goto BeforeRet;$n", [])
|
||||||
|
|
||||||
proc genComputedGoto(p: BProc; n: PNode) =
|
proc genComputedGoto(p: BProc; n: PNode) =
|
||||||
# first pass: Generate array of computed labels:
|
# first pass: Generate array of computed labels:
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
|
||||||
# C type generation into an analysis and a code generation phase somehow.
|
# C type generation into an analysis and a code generation phase somehow.
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyRef, tyPtr, tyVar:
|
of tyRef, tyPtr, tyVar:
|
||||||
let star = if t.kind == tyVar and compileToCpp(m): "&" else: "*"
|
var star = if t.kind == tyVar and compileToCpp(m): "&" else: "*"
|
||||||
var et = t.lastSon
|
var et = t.lastSon
|
||||||
var etB = et.skipTypes(abstractInst)
|
var etB = et.skipTypes(abstractInst)
|
||||||
if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}:
|
if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}:
|
||||||
|
|
@ -514,6 +514,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
|
||||||
# ``var set[char]`` in `getParamTypeDesc`
|
# ``var set[char]`` in `getParamTypeDesc`
|
||||||
et = elemType(etB)
|
et = elemType(etB)
|
||||||
etB = et.skipTypes(abstractInst)
|
etB = et.skipTypes(abstractInst)
|
||||||
|
star[0] = '*'
|
||||||
case etB.kind
|
case etB.kind
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
if isImportedCppType(etB) and et.kind == tyGenericInst:
|
if isImportedCppType(etB) and et.kind == tyGenericInst:
|
||||||
|
|
@ -529,7 +530,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
|
||||||
# no restriction! We have a forward declaration for structs
|
# no restriction! We have a forward declaration for structs
|
||||||
let x = getUniqueType(etB)
|
let x = getUniqueType(etB)
|
||||||
let name = getTypeForward(m, x)
|
let name = getTypeForward(m, x)
|
||||||
result = con(name, "**")
|
result = con(name, "*" & star)
|
||||||
idTablePut(m.typeCache, t, result)
|
idTablePut(m.typeCache, t, result)
|
||||||
pushType(m, x)
|
pushType(m, x)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -137,78 +137,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
app(result, substr(frmt, start, i - 1))
|
app(result, substr(frmt, start, i - 1))
|
||||||
|
|
||||||
const compileTimeRopeFmt = false
|
template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr =
|
||||||
|
|
||||||
when compileTimeRopeFmt:
|
|
||||||
import macros
|
|
||||||
|
|
||||||
type TFmtFragmentKind = enum
|
|
||||||
ffSym,
|
|
||||||
ffLit,
|
|
||||||
ffParam
|
|
||||||
|
|
||||||
type TFragment = object
|
|
||||||
case kind: TFmtFragmentKind
|
|
||||||
of ffSym, ffLit:
|
|
||||||
value: string
|
|
||||||
of ffParam:
|
|
||||||
intValue: int
|
|
||||||
|
|
||||||
iterator fmtStringFragments(s: string): tuple[kind: TFmtFragmentKind,
|
|
||||||
value: string,
|
|
||||||
intValue: int] =
|
|
||||||
# This is a bit less featured version of the ropecg's algorithm
|
|
||||||
# (be careful when replacing ropecg calls)
|
|
||||||
var
|
|
||||||
i = 0
|
|
||||||
length = s.len
|
|
||||||
|
|
||||||
while i < length:
|
|
||||||
var start = i
|
|
||||||
case s[i]
|
|
||||||
of '$':
|
|
||||||
let n = s[i+1]
|
|
||||||
case n
|
|
||||||
of '$':
|
|
||||||
inc i, 2
|
|
||||||
of '0'..'9':
|
|
||||||
# XXX: use the new case object construction syntax when it's ready
|
|
||||||
yield (kind: ffParam, value: "", intValue: n.ord - ord('1'))
|
|
||||||
inc i, 2
|
|
||||||
start = i
|
|
||||||
else:
|
|
||||||
inc i
|
|
||||||
of '#':
|
|
||||||
inc i
|
|
||||||
var j = i
|
|
||||||
while s[i] in IdentChars: inc i
|
|
||||||
yield (kind: ffSym, value: substr(s, j, i-1), intValue: 0)
|
|
||||||
start = i
|
|
||||||
else: discard
|
|
||||||
|
|
||||||
while i < length:
|
|
||||||
if s[i] != '$' and s[i] != '#': inc i
|
|
||||||
else: break
|
|
||||||
|
|
||||||
if i - 1 >= start:
|
|
||||||
yield (kind: ffLit, value: substr(s, start, i-1), intValue: 0)
|
|
||||||
|
|
||||||
macro rfmt(m: BModule, fmt: static[string], args: varargs[PRope]): expr =
|
|
||||||
## Experimental optimized rope-formatting operator
|
|
||||||
## The run-time code it produces will be very fast, but will it speed up
|
|
||||||
## the compilation of nimrod itself or will the macro execution time
|
|
||||||
## offset the gains?
|
|
||||||
result = newCall(bindSym"ropeConcat")
|
|
||||||
for frag in fmtStringFragments(fmt):
|
|
||||||
case frag.kind
|
|
||||||
of ffSym:
|
|
||||||
result.add(newCall(bindSym"cgsym", m, newStrLitNode(frag.value)))
|
|
||||||
of ffLit:
|
|
||||||
result.add(newCall(bindSym"~", newStrLitNode(frag.value)))
|
|
||||||
of ffParam:
|
|
||||||
result.add(args[frag.intValue])
|
|
||||||
else:
|
|
||||||
template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr =
|
|
||||||
ropecg(m, fmt, args)
|
ropecg(m, fmt, args)
|
||||||
|
|
||||||
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
||||||
|
|
@ -242,12 +171,7 @@ proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||||
args: varargs[PRope]) =
|
args: varargs[PRope]) =
|
||||||
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
|
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
|
||||||
|
|
||||||
when compileTimeRopeFmt:
|
proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||||
template linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
|
||||||
args: varargs[PRope]) =
|
|
||||||
line(p, s, rfmt(p.module, frmt, args))
|
|
||||||
else:
|
|
||||||
proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
|
||||||
args: varargs[PRope]) =
|
args: varargs[PRope]) =
|
||||||
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
|
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
|
||||||
|
|
||||||
|
|
@ -255,11 +179,6 @@ proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr,
|
||||||
args: varargs[PRope]) =
|
args: varargs[PRope]) =
|
||||||
app(r, indentLine(p, ropecg(p.module, frmt, args)))
|
app(r, indentLine(p, ropecg(p.module, frmt, args)))
|
||||||
|
|
||||||
proc lineFF(p: BProc, s: TCProcSection, cformat, llvmformat: string,
|
|
||||||
args: varargs[PRope]) =
|
|
||||||
if gCmd == cmdCompileToLLVM: lineF(p, s, llvmformat, args)
|
|
||||||
else: lineF(p, s, cformat, args)
|
|
||||||
|
|
||||||
proc safeLineNm(info: TLineInfo): int =
|
proc safeLineNm(info: TLineInfo): int =
|
||||||
result = toLinenumber(info)
|
result = toLinenumber(info)
|
||||||
if result < 0: result = 0 # negative numbers are not allowed in #line
|
if result < 0: result = 0 # negative numbers are not allowed in #line
|
||||||
|
|
@ -809,9 +728,10 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
|
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
|
||||||
# invoke at proc entry for recursion:
|
# invoke at proc entry for recursion:
|
||||||
appcg(p, cpsInit, "\t#nimProfile();$n", [])
|
appcg(p, cpsInit, "\t#nimProfile();$n", [])
|
||||||
|
if p.beforeRetNeeded: app(generatedProc, "{")
|
||||||
app(generatedProc, p.s(cpsInit))
|
app(generatedProc, p.s(cpsInit))
|
||||||
app(generatedProc, p.s(cpsStmts))
|
app(generatedProc, p.s(cpsStmts))
|
||||||
if p.beforeRetNeeded: app(generatedProc, ~"\tBeforeRet: ;$n")
|
if p.beforeRetNeeded: app(generatedProc, ~"\t}BeforeRet: ;$n")
|
||||||
app(generatedProc, deinitGCFrame(p))
|
app(generatedProc, deinitGCFrame(p))
|
||||||
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
|
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
|
||||||
app(generatedProc, returnStmt)
|
app(generatedProc, returnStmt)
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ type
|
||||||
maxFrameLen*: int # max length of frame descriptor
|
maxFrameLen*: int # max length of frame descriptor
|
||||||
module*: BModule # used to prevent excessive parameter passing
|
module*: BModule # used to prevent excessive parameter passing
|
||||||
withinLoop*: int # > 0 if we are within a loop
|
withinLoop*: int # > 0 if we are within a loop
|
||||||
|
splitDecls*: int # > 0 if we are in some context for C++ that
|
||||||
|
# requires 'T x = T()' to become 'T x; x = T()'
|
||||||
|
# (yes, C++ is weird like that)
|
||||||
gcFrameId*: Natural # for the GC stack marking
|
gcFrameId*: Natural # for the GC stack marking
|
||||||
gcFrameType*: PRope # the struct {} we put the GC markers into
|
gcFrameType*: PRope # the struct {} we put the GC markers into
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
|
||||||
|
|
||||||
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
|
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
|
if gCmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return
|
||||||
var n = result.PNode
|
var n = result.PNode
|
||||||
case n.sons[0].kind
|
case n.sons[0].kind
|
||||||
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
|
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
|
||||||
|
|
|
||||||
|
|
@ -1074,6 +1074,10 @@ when defined(windows):
|
||||||
# because we support Windows GUI applications, things get really
|
# because we support Windows GUI applications, things get really
|
||||||
# messy here...
|
# messy here...
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
|
when defined(cpp):
|
||||||
|
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
||||||
|
importcpp: "(NI16*)wcschr((const wchar_t *)#, #)", header: "<string.h>".}
|
||||||
|
else:
|
||||||
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
||||||
importc: "wcschr", header: "<string.h>".}
|
importc: "wcschr", header: "<string.h>".}
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -84,16 +84,18 @@ elif defined(windows) or defined(dos):
|
||||||
type
|
type
|
||||||
THINSTANCE {.importc: "HINSTANCE".} = object
|
THINSTANCE {.importc: "HINSTANCE".} = object
|
||||||
x: pointer
|
x: pointer
|
||||||
|
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
|
||||||
|
importcpp: "(void*)GetProcAddress(@)", header: "<windows.h>", stdcall.}
|
||||||
else:
|
else:
|
||||||
type
|
type
|
||||||
THINSTANCE {.importc: "HINSTANCE".} = pointer
|
THINSTANCE {.importc: "HINSTANCE".} = pointer
|
||||||
|
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
|
||||||
|
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
||||||
|
|
||||||
proc freeLibrary(lib: THINSTANCE) {.
|
proc freeLibrary(lib: THINSTANCE) {.
|
||||||
importc: "FreeLibrary", header: "<windows.h>", stdcall.}
|
importc: "FreeLibrary", header: "<windows.h>", stdcall.}
|
||||||
proc winLoadLibrary(path: cstring): THINSTANCE {.
|
proc winLoadLibrary(path: cstring): THINSTANCE {.
|
||||||
importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
|
importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
|
||||||
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
|
|
||||||
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
|
||||||
|
|
||||||
proc nimUnloadLibrary(lib: TLibHandle) =
|
proc nimUnloadLibrary(lib: TLibHandle) =
|
||||||
freeLibrary(cast[THINSTANCE](lib))
|
freeLibrary(cast[THINSTANCE](lib))
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,12 @@ when (defined(windows) and not defined(useWinAnsi)) or defined(nimdoc):
|
||||||
include "system/widestrs"
|
include "system/widestrs"
|
||||||
|
|
||||||
when defined(windows) and not defined(useWinAnsi):
|
when defined(windows) and not defined(useWinAnsi):
|
||||||
|
when defined(cpp):
|
||||||
|
proc wfopen(filename, mode: WideCString): pointer {.
|
||||||
|
importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.}
|
||||||
|
proc wfreopen(filename, mode: WideCString, stream: File): File {.
|
||||||
|
importc: "_wfreopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.}
|
||||||
|
else:
|
||||||
proc wfopen(filename, mode: WideCString): pointer {.
|
proc wfopen(filename, mode: WideCString): pointer {.
|
||||||
importc: "_wfopen", nodecl.}
|
importc: "_wfopen", nodecl.}
|
||||||
proc wfreopen(filename, mode: WideCString, stream: File): File {.
|
proc wfreopen(filename, mode: WideCString, stream: File): File {.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue