mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
Asm syntax pragma (#23119)
(Inspired by this pragma in nir asm PR)
`inlineAsmSyntax` pragma allowing specify target inline assembler syntax
in `asm` stmt.
It prevents compiling code with different of the target CC inline asm
syntax, i.e. it will not allow gcc inline asm code to be compiled with
vcc.
```nim
proc nothing() =
asm {.inlineAsmSyntax: "gcc".} """
nop
"""
```
The current C(C++) backend implementation cannot generate code for gcc
and for vcc at the same time. For example, `{.inlineAsmSyntax: "vcc".}`
with the ICC compiler will not generate code with intel asm syntax, even
though ICC can use both gcc-like asm and vcc-like. For implement support
for gcc and for vcc at the same time in ICC compiler, we need to
refactor extccomp
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
@@ -1537,6 +1537,21 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||
assert(t.kind == nkAsmStmt)
|
||||
genLineDir(p, t)
|
||||
var s = newRopeAppender()
|
||||
|
||||
var asmSyntax = ""
|
||||
if (let p = t[0]; p.kind == nkPragma):
|
||||
for i in p:
|
||||
if whichPragma(i) == wAsmSyntax:
|
||||
asmSyntax = i[1].strVal
|
||||
|
||||
if asmSyntax != "" and
|
||||
not (
|
||||
asmSyntax == "gcc" and hasGnuAsm in CC[p.config.cCompiler].props or
|
||||
asmSyntax == "vcc" and hasGnuAsm notin CC[p.config.cCompiler].props):
|
||||
localError(
|
||||
p.config, t.info,
|
||||
"Your compiler does not support the specified inline assembler")
|
||||
|
||||
genAsmOrEmitStmt(p, t, isAsmStmt=true, s)
|
||||
# see bug #2362, "top level asm statements" seem to be a mis-feature
|
||||
# but even if we don't do this, the example in #2362 cannot possibly
|
||||
|
||||
@@ -153,20 +153,6 @@ proc pragmaEnsures(c: PContext, n: PNode) =
|
||||
n[1] = c.semExpr(c, n[1])
|
||||
closeScope(c)
|
||||
|
||||
proc pragmaAsm*(c: PContext, n: PNode): char =
|
||||
result = '\0'
|
||||
if n != nil:
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind in nkPragmaCallKinds and it.len == 2 and it[0].kind == nkIdent:
|
||||
case whichKeyword(it[0].ident)
|
||||
of wSubsChar:
|
||||
if it[1].kind == nkCharLit: result = chr(int(it[1].intVal))
|
||||
else: invalidPragma(c, it)
|
||||
else: invalidPragma(c, it)
|
||||
else:
|
||||
invalidPragma(c, it)
|
||||
|
||||
proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) =
|
||||
# special cases to improve performance:
|
||||
if extname == "$1":
|
||||
@@ -307,6 +293,24 @@ proc pragmaNoForward*(c: PContext, n: PNode; flag=sfNoForward) =
|
||||
"use {.experimental: \"codeReordering\".} instead; " &
|
||||
(if flag == sfNoForward: "{.noForward.}" else: "{.reorder.}") & " is deprecated")
|
||||
|
||||
proc pragmaAsm*(c: PContext, n: PNode): char =
|
||||
## Checks asm pragmas and get's the asm subschar (default: '`').
|
||||
result = '\0'
|
||||
if n != nil:
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind in nkPragmaCallKinds and it.len == 2 and it[0].kind == nkIdent:
|
||||
case whichKeyword(it[0].ident)
|
||||
of wSubsChar:
|
||||
if it[1].kind == nkCharLit: result = chr(int(it[1].intVal))
|
||||
else: invalidPragma(c, it)
|
||||
of wAsmSyntax:
|
||||
let s = expectStrLit(c, it)
|
||||
if s notin ["gcc", "vcc"]: invalidPragma(c, it)
|
||||
else: invalidPragma(c, it)
|
||||
else:
|
||||
invalidPragma(c, it)
|
||||
|
||||
proc processCallConv(c: PContext, n: PNode) =
|
||||
if n.kind in nkPragmaCallKinds and n.len == 2 and n[1].kind == nkIdent:
|
||||
let sw = whichKeyword(n[1].ident)
|
||||
|
||||
@@ -84,7 +84,7 @@ type
|
||||
wComputedGoto = "computedGoto", wExperimental = "experimental", wDoctype = "doctype",
|
||||
wWrite = "write", wGensym = "gensym", wInject = "inject", wDirty = "dirty",
|
||||
wInheritable = "inheritable", wThreadVar = "threadvar", wEmit = "emit",
|
||||
wAsmNoStackFrame = "asmNoStackFrame", wImplicitStatic = "implicitStatic",
|
||||
wAsmNoStackFrame = "asmNoStackFrame", wAsmSyntax = "asmSyntax", wImplicitStatic = "implicitStatic",
|
||||
wGlobal = "global", wCodegenDecl = "codegenDecl", wUnchecked = "unchecked",
|
||||
wGuard = "guard", wLocks = "locks", wPartial = "partial", wExplain = "explain",
|
||||
wLiftLocals = "liftlocals", wEnforceNoRaises = "enforceNoRaises", wSystemRaisesDefect = "systemRaisesDefect",
|
||||
|
||||
@@ -2595,3 +2595,20 @@ method foo(x: Base) {.base.} = discard
|
||||
```
|
||||
|
||||
It gives an error: method `foo` can be defined only in the same module with its type (Base).
|
||||
|
||||
|
||||
asmSyntax pragma
|
||||
================
|
||||
|
||||
The `asmSyntax` pragma is used to specify target inline assembler syntax in an `asm` statement.
|
||||
|
||||
It prevents compiling code with different of the target CC inline asm syntax, i.e. it will not allow gcc inline asm code to be compiled with vcc.
|
||||
|
||||
```nim
|
||||
proc nothing() =
|
||||
asm {.asmSyntax: "gcc".}"""
|
||||
nop
|
||||
"""
|
||||
```
|
||||
|
||||
The current C(C++) backend implementation cannot generate code for gcc and for vcc at the same time. For example, `{.asmSyntax: "vcc".}` with the ICC compiler will not generate code with intel asm syntax, even though ICC can use both gcc-like and vcc-like asm.
|
||||
|
||||
Reference in New Issue
Block a user