Use typeflag instead

This commit is contained in:
Clyybber 2020-08-10 12:57:32 +02:00
commit b022576ce9
11 changed files with 29 additions and 18 deletions

View file

@ -17,8 +17,7 @@ export int128
type type
TCallingConvention* = enum TCallingConvention* = enum
ccImplicit, # proc has no explicit calling convention ccNimCall, # nimcall, also the default
ccNimCall, # proc was explicitly marked as nimcall
ccStdCall, # procedure is stdcall ccStdCall, # procedure is stdcall
ccCDecl, # cdecl ccCDecl, # cdecl
ccSafeCall, # safecall ccSafeCall, # safecall
@ -31,12 +30,10 @@ type
ccNoConvention # needed for generating proper C procs sometimes ccNoConvention # needed for generating proper C procs sometimes
const const
ccDefault* = {ccImplicit, ccNimCall} CallingConvToStr*: array[TCallingConvention, string] = ["nimcall", "stdcall",
CallingConvToStr*: array[TCallingConvention, string] = ["", "nimcall", "stdcall",
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall", "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall",
"closure", "noconv"] "closure", "noconv"]
type type
TNodeKind* = enum # order is extremely important, because ranges are used TNodeKind* = enum # order is extremely important, because ranges are used
# to check whether a node belongs to a certain class # to check whether a node belongs to a certain class
@ -563,6 +560,7 @@ type
tfCompleteStruct tfCompleteStruct
# (for importc types); type is fully specified, allowing to compute # (for importc types); type is fully specified, allowing to compute
# sizeof, alignof, offsetof at CT # sizeof, alignof, offsetof at CT
tfExplicitCallConv
TTypeFlags* = set[TTypeFlag] TTypeFlags* = set[TTypeFlag]

View file

@ -1240,7 +1240,7 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a # the prototype of a destructor is ``=destroy(x: var T)`` and that of a
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling # finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
# convention at least: # convention at least:
if bt.destructor.typ == nil or bt.destructor.typ.callConv notin ccDefault: if bt.destructor.typ == nil or bt.destructor.typ.callConv != ccNimCall:
localError(p.module.config, a.lode.info, localError(p.module.config, a.lode.info,
"the destructor that is turned into a finalizer needs " & "the destructor that is turned into a finalizer needs " &
"to have the 'nimcall' calling convention") "to have the 'nimcall' calling convention")

View file

@ -234,7 +234,7 @@ proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool =
else: result = false else: result = false
const const
CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", "N_NIMCALL", CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL",
"N_STDCALL", "N_CDECL", "N_SAFECALL", "N_STDCALL", "N_CDECL", "N_SAFECALL",
"N_SYSCALL", # this is probably not correct for all platforms, "N_SYSCALL", # this is probably not correct for all platforms,
# but one can #define it to what one wants # but one can #define it to what one wants
@ -1297,7 +1297,7 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a # the prototype of a destructor is ``=destroy(x: var T)`` and that of a
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling # finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
# convention at least: # convention at least:
if theProc.typ == nil or theProc.typ.callConv notin ccDefault: if theProc.typ == nil or theProc.typ.callConv != ccNimCall:
localError(m.config, info, localError(m.config, info,
theProc.name.s & " needs to have the 'nimcall' calling convention") theProc.name.s & " needs to have the 'nimcall' calling convention")

View file

@ -104,7 +104,7 @@ proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.Type =
proc mapCallConv(conf: ConfigRef, cc: TCallingConvention, info: TLineInfo): TABI = proc mapCallConv(conf: ConfigRef, cc: TCallingConvention, info: TLineInfo): TABI =
case cc case cc
of ccDefault: result = DEFAULT_ABI of ccNimCall: result = DEFAULT_ABI
of ccStdCall: result = when defined(windows) and defined(x86): STDCALL else: DEFAULT_ABI of ccStdCall: result = when defined(windows) and defined(x86): STDCALL else: DEFAULT_ABI
of ccCDecl: result = DEFAULT_ABI of ccCDecl: result = DEFAULT_ABI
else: else:

View file

@ -293,7 +293,7 @@ proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
("'$1' is of type <$2> which cannot be captured as it would violate memory" & ("'$1' is of type <$2> which cannot be captured as it would violate memory" &
" safety, declared here: $3; using '-d:nimWorkaround14447' helps in some cases") % " safety, declared here: $3; using '-d:nimWorkaround14447' helps in some cases") %
[s.name.s, typeToString(s.typ), g.config$s.info]) [s.name.s, typeToString(s.typ), g.config$s.info])
elif owner.typ.callConv notin {ccClosure, ccImplicit}: elif not (owner.typ.callConv == ccClosure or owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags):
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" % localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
[s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]]) [s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]])
incl(owner.typ.flags, tfCapturesEnv) incl(owner.typ.flags, tfCapturesEnv)
@ -822,7 +822,8 @@ proc semCaptureSym*(s, owner: PSym) =
var o = owner.skipGenericOwner var o = owner.skipGenericOwner
while o != nil and o.kind != skModule: while o != nil and o.kind != skModule:
if s.owner == o: if s.owner == o:
if owner.typ.callConv in {ccClosure, ccImplicit} or owner.kind == skIterator: if owner.typ.callConv == ccClosure or owner.kind == skIterator or
owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags:
owner.typ.callConv = ccClosure owner.typ.callConv = ccClosure
propagateClosure(owner.skipGenericOwner, s.owner) propagateClosure(owner.skipGenericOwner, s.owner)
else: else:

View file

@ -326,7 +326,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
# a calling convention that doesn't introduce custom name mangling # a calling convention that doesn't introduce custom name mangling
# cdecl is the default - the user can override this explicitly # cdecl is the default - the user can override this explicitly
if sym.kind in routineKinds and sym.typ != nil and if sym.kind in routineKinds and sym.typ != nil and
sym.typ.callConv == ccImplicit: tfExplicitCallConv notin sym.typ.flags:
sym.typ.callConv = ccCDecl sym.typ.callConv = ccCDecl
proc processNote(c: PContext, n: PNode) = proc processNote(c: PContext, n: PNode) =
@ -1061,7 +1061,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of FirstCallConv..LastCallConv: of FirstCallConv..LastCallConv:
assert(sym != nil) assert(sym != nil)
if sym.typ == nil: invalidPragma(c, it) if sym.typ == nil: invalidPragma(c, it)
else: sym.typ.callConv = wordToCallConv(k) else:
sym.typ.callConv = wordToCallConv(k)
sym.typ.flags.incl tfExplicitCallConv
of wEmit: pragmaEmit(c, it) of wEmit: pragmaEmit(c, it)
of wUnroll: pragmaUnroll(c, it) of wUnroll: pragmaUnroll(c, it)
of wLinearScanEnd, wComputedGoto: noVal(c, it) of wLinearScanEnd, wComputedGoto: noVal(c, it)

View file

@ -212,7 +212,7 @@ proc considerGenSyms*(c: PContext; n: PNode) =
proc newOptionEntry*(conf: ConfigRef): POptionEntry = proc newOptionEntry*(conf: ConfigRef): POptionEntry =
new(result) new(result)
result.options = conf.options result.options = conf.options
result.defaultCC = ccImplicit result.defaultCC = ccNimCall
result.dynlib = nil result.dynlib = nil
result.notes = conf.notes result.notes = conf.notes
result.warningAsErrors = conf.warningAsErrors result.warningAsErrors = conf.warningAsErrors

View file

@ -639,11 +639,11 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
return isNone return isNone
elif f.callConv != a.callConv: elif f.callConv != a.callConv:
# valid to pass a 'nimcall' thingie to 'closure': # valid to pass a 'nimcall' thingie to 'closure':
if f.callConv == ccClosure and a.callConv in ccDefault: if f.callConv == ccClosure and a.callConv == ccNimCall:
result = if result == isInferred: isInferredConvertible result = if result == isInferred: isInferredConvertible
elif result == isBothMetaConvertible: isBothMetaConvertible elif result == isBothMetaConvertible: isBothMetaConvertible
else: isConvertible else: isConvertible
elif not(f.callConv in ccDefault and a.callConv in ccDefault): else:
return isNone return isNone
when useEffectSystem: when useEffectSystem:
if compatibleEffects(f, a) != efCompat: return isNone if compatibleEffects(f, a) != efCompat: return isNone

View file

@ -539,7 +539,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
# happens sometimes for generated assignments, etc. # happens sometimes for generated assignments, etc.
of tyProc: of tyProc:
result = transformSons(c, n) result = transformSons(c, n)
if dest.callConv == ccClosure and source.callConv in ccDefault: if dest.callConv == ccClosure and source.callConv == ccNimCall:
result = generateThunk(c, result[1], dest) result = generateThunk(c, result[1], dest)
else: else:
result = transformSons(c, n) result = transformSons(c, n)

View file

@ -679,7 +679,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if i < t.len - 1: result.add(", ") if i < t.len - 1: result.add(", ")
result.add(')') result.add(')')
if t.len > 0 and t[0] != nil: result.add(": " & typeToString(t[0])) if t.len > 0 and t[0] != nil: result.add(": " & typeToString(t[0]))
var prag = if t.callConv == ccImplicit: "" else: CallingConvToStr[t.callConv] var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: CallingConvToStr[t.callConv]
if tfNoSideEffect in t.flags: if tfNoSideEffect in t.flags:
addSep(prag) addSep(prag)
prag.add("noSideEffect") prag.add("noSideEffect")

View file

@ -0,0 +1,10 @@
discard """
errormsg: "type mismatch: got <proc (){.closure, gcsafe, locks: 0.}> but expected 'A = proc (){.nimcall.}'"
line: 9
"""
type A = proc() {.nimcall.}
proc main =
let b = 1
let a: A = proc() = echo b