summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorASVIEST <71895914+ASVIEST@users.noreply.github.com>2023-12-25 09:12:54 +0300
committerGitHub <noreply@github.com>2023-12-25 07:12:54 +0100
commit1324d2e04cb11aaa96e9ba9efc69aee47ed6c1d8 (patch)
tree65b57ab57bac497235be76ec1a3b49c46461b8a9
parent6f3d3fdf9f4a718a7365ab98455903a7b18dade8 (diff)
downloadNim-1324d2e04cb11aaa96e9ba9efc69aee47ed6c1d8.tar.gz
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>
-rw-r--r--compiler/ccgstmts.nim15
-rw-r--r--compiler/pragmas.nim32
-rw-r--r--compiler/wordrecg.nim2
-rw-r--r--doc/manual_experimental.md17
4 files changed, 51 insertions, 15 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 7bbc40890..28c0851aa 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -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
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 001af6ae7..a4c539799 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -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)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 55a8921af..39e0b2e25 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -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",
diff --git a/doc/manual_experimental.md b/doc/manual_experimental.md
index 765a69a0f..9b52fbd2a 100644
--- a/doc/manual_experimental.md
+++ b/doc/manual_experimental.md
@@ -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.