-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
NIR: asm statement support, Wip #22992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 5 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
ddaea3b
Asm (gcc extended asm) for nir
ASVIEST 73eb391
Update genasm.nim
ASVIEST 73f9b60
Asm parsing now working on backends (WIP(
ASVIEST a4ddb3b
Emit targets
ASVIEST 03af260
Remove asm instrs
ASVIEST 545d35a
Update nirinsts.nim
ASVIEST 5cefc65
verbatims
ASVIEST cd5de29
gcc asm (simple)
ASVIEST c0ab580
fix lastSon
ASVIEST 78a4c61
Seperated file
ASVIEST e4af3f0
target properties
ASVIEST e9221ae
GCC asm c codegen
ASVIEST 8419151
Small fix
ASVIEST 57802ed
apply suggestions
ASVIEST a1f9c3f
msvc asm
ASVIEST f41557d
info's
ASVIEST fc8b91f
fix
ASVIEST 68bc65d
fix
ASVIEST 3d4f45e
Extended asm is now default inline asm syntax
ASVIEST 119e15b
Merge branch 'devel' into nir-asm
ASVIEST 24b6c55
support asmNoStackFrame
ASVIEST bb463f1
Merge branch 'nir-asm' of https://github.com/ASVIEST/Nim into nir-asm
ASVIEST 5f58ec9
use strings for verbatims
ASVIEST 330ae88
fix asmNoStackFrame
ASVIEST 21ee838
fix
ASVIEST cc45710
small refactor
ASVIEST 1b88194
Merge branch 'nim-lang:devel' into nir-asm
ASVIEST c7d3093
Merge branch 'nim-lang:devel' into nir-asm
ASVIEST 11a6fe8
inlineAsmSyntax pragma
ASVIEST ec8beea
Merge branch 'nim-lang:devel' into nir-asm
ASVIEST 540ef8f
simple dialect switch
ASVIEST 5d6c354
Update cir.nim
ASVIEST f0efd4c
Update cir.nim
ASVIEST 811e6ab
Revert "Update cir.nim"
ASVIEST 94c7fa0
Merge branch 'nim-lang:devel' into nir-asm
ASVIEST 747ead5
Merge branch 'nim-lang:devel' into nir-asm
ASVIEST File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,314 @@ | ||
# generates Asm stategments like this: | ||
# Asm { | ||
# AsmTemplate { | ||
# Some asm code | ||
# SymUse nimInlineVar # `a` | ||
# Some asm code | ||
# } | ||
# AsmOutputOperand { | ||
# # [asmSymbolicName] constraint (nimVariableName) | ||
# AsmInjectExpr {symUse nimVariableName} # for output it have only one sym (lvalue) | ||
# asmSymbolicName # default: "" | ||
# constraint | ||
# } | ||
# AsmInputOperand { | ||
# # [asmSymbolicName] constraint (nimExpr) | ||
# AsmInjectExpr {symUse nimVariableName} # (rvalue) | ||
# asmSymbolicName # default: "" | ||
# constraint | ||
# } | ||
# AsmClobber { | ||
# "clobber" | ||
# } | ||
|
||
# it can be useful for better asm analysis and | ||
# easy to use in all nim targets | ||
import nirinsts, nirtypes | ||
import std / assertions | ||
import .. / ic / bitabs | ||
|
||
type | ||
Det = enum | ||
AsmTemplate | ||
SymbolicName | ||
InjectExpr | ||
Constraint | ||
Clobber | ||
Delimiter | ||
|
||
AsmValKind = enum | ||
StrVal | ||
# SymVal | ||
NodeVal | ||
EmptyVal | ||
|
||
AsmVal = object | ||
case kind: AsmValKind | ||
of StrVal: | ||
s: string | ||
# of SymVal: | ||
# sym: SymId | ||
of NodeVal: | ||
n: NodePos | ||
of EmptyVal: | ||
discard | ||
|
||
AsmToken = tuple[sec: int, val: AsmVal, det: Det] | ||
|
||
AsmNodeKind* = enum | ||
AsmTemplate | ||
AsmOutputOperand | ||
AsmInputOperand | ||
AsmClobber | ||
|
||
AsmInjectExpr | ||
AsmStrVal | ||
|
||
GccAsmNode* = ref object | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not how we write ASTs in Nim 2023. We now use "packed trees". The files you have touched can guide you. |
||
case kind: AsmNodeKind | ||
of AsmTemplate: | ||
instrs: seq[GccAsmNode] | ||
of AsmOutputOperand, AsmInputOperand: | ||
symbolicName: string | ||
constraint: string | ||
injectExpr: GccAsmNode | ||
of AsmClobber: | ||
clobber: string | ||
of AsmStrVal: | ||
s: string | ||
of AsmInjectExpr: | ||
n: NodePos | ||
|
||
|
||
proc toVal(n: NodePos): AsmVal = | ||
AsmVal(kind: NodeVal, n: n) | ||
|
||
proc toVal(s: string): AsmVal = | ||
AsmVal(kind: StrVal, s: s) | ||
|
||
# proc toVal(s: SymId): AsmVal = | ||
# AsmVal(kind: SymVal, sym: s) | ||
|
||
proc empty(): AsmVal = | ||
AsmVal(kind: EmptyVal) | ||
|
||
proc toNode(val: AsmVal): GccAsmNode = | ||
# get str node or | ||
case val.kind: | ||
of StrVal: GccAsmNode(kind: AsmStrVal, s: val.s) | ||
of NodeVal: GccAsmNode(kind: AsmInjectExpr, n: val.n) | ||
else: raiseAssert"unsupported val" | ||
|
||
proc emptyNode(kind: AsmNodeKind): GccAsmNode = | ||
GccAsmNode(kind: kind) | ||
|
||
iterator asmTokens(t: Tree, n: NodePos; lit: Literals): AsmToken = | ||
template addCaptured: untyped = | ||
yield ( | ||
sec, | ||
captured.toVal, | ||
det | ||
) | ||
captured = "" | ||
|
||
template maybeAddCaptured: untyped = | ||
if captured != "": | ||
addCaptured() | ||
|
||
var sec = 0 | ||
var det: Det = AsmTemplate | ||
var left = 0 | ||
var captured = "" | ||
|
||
# handling comments | ||
var | ||
inComment = false # current char in comment(note: comment chars is skipped) | ||
isLineComment = false | ||
foundCommentStartSym = false | ||
foundCommentEndSym = false | ||
|
||
for ch in sons(t, n): | ||
case t[ch].kind | ||
of Verbatim: | ||
let s = ""#it.strVal | ||
|
||
for i in 0..s.high: | ||
|
||
# Comments | ||
if sec > 0 and foundCommentStartSym: | ||
# "/?" | ||
if s[i] == '/': | ||
# "//" | ||
inComment = true | ||
isLineComment = true | ||
elif s[i] == '*': | ||
# "/*" | ||
inComment = true | ||
isLineComment = false | ||
foundCommentStartSym = false # updates it | ||
|
||
if sec > 0 and not foundCommentStartSym and s[i] == '*': | ||
#"(!/)*" | ||
foundCommentEndSym = true | ||
elif sec > 0 and foundCommentEndSym: # "*?" | ||
if s[i] == '/': # "*/" | ||
inComment = false | ||
# delete captured '/' | ||
captured = "" | ||
continue | ||
foundCommentEndSym = false | ||
if sec > 0 and s[i] == '/': # '/' | ||
foundCommentStartSym = true | ||
if sec > 0 and s[i] == '\n' and inComment: | ||
if not isLineComment: # /* comment \n | ||
raiseAssert """expected "*/", not "*""" & s[i] & """" in asm operand""" | ||
inComment = false | ||
# delete captured '/' | ||
captured = "" | ||
continue | ||
if inComment: | ||
# skip commented syms | ||
continue | ||
|
||
|
||
|
||
case s[i]: | ||
of ':': | ||
if sec == 0: # det == AsmTemplate | ||
yield ( | ||
sec, | ||
s[left..i - 1].toVal, | ||
det | ||
) | ||
|
||
inc sec | ||
# inc det | ||
left = i + 1 | ||
captured = "" | ||
|
||
if sec in 1..2: | ||
# default det for operands | ||
det = Constraint | ||
elif sec == 3: | ||
det = Clobber | ||
|
||
of '[': | ||
# start of asm symbolic name | ||
det = SymbolicName | ||
|
||
of ']': | ||
if det != SymbolicName: | ||
raiseAssert "expected: ']'" | ||
|
||
addCaptured() | ||
|
||
det = Constraint | ||
# s[capturedStart .. i - 1] | ||
|
||
of '(': | ||
addCaptured() # add asm constraint | ||
det = InjectExpr | ||
|
||
of ')': | ||
if det != InjectExpr: | ||
raiseAssert "expected: ')'" | ||
|
||
maybeAddCaptured() | ||
|
||
elif sec > 0 and s[i] == ',': | ||
if sec in 1..2: | ||
det = Constraint | ||
|
||
if sec == 3: | ||
maybeAddCaptured() | ||
|
||
yield ( | ||
sec, | ||
empty(), | ||
Delimiter | ||
) | ||
|
||
elif ( | ||
sec > 0 and | ||
det in { | ||
SymbolicName, | ||
Constraint, | ||
InjectExpr, | ||
Clobber | ||
} and | ||
s[i] notin {' ', '\n', '\t'} | ||
): captured.add s[i] | ||
|
||
|
||
else: discard | ||
|
||
else: | ||
maybeAddCaptured() | ||
|
||
yield ( | ||
sec, | ||
ch.toVal, | ||
det | ||
) | ||
|
||
left = 0 | ||
|
||
if sec == 0: | ||
# : not specified | ||
yield ( | ||
sec, | ||
lit.strings[t[lastSon(t, n)].litId].toVal, | ||
det | ||
) | ||
elif sec > 2: | ||
maybeAddCaptured() | ||
|
||
const | ||
sections = [ | ||
AsmNodeKind.AsmTemplate, | ||
AsmOutputOperand, | ||
AsmInputOperand, | ||
AsmClobber | ||
] | ||
|
||
iterator parseGccAsm*(t: Tree, n: NodePos; lit: Literals): GccAsmNode = | ||
var | ||
oldSec = 0 | ||
curr = emptyNode(AsmTemplate) | ||
inInjectExpr = false | ||
|
||
template initNextNode: untyped = | ||
curr = emptyNode(sections[i.sec]) | ||
|
||
for i in asmTokens(t, n, lit): | ||
if i.sec != oldSec: | ||
# current node fully filled | ||
yield curr | ||
initNextNode() | ||
|
||
case i.det: | ||
of Delimiter: | ||
yield curr | ||
initNextNode() | ||
|
||
of AsmTemplate: | ||
curr.instrs.add i.val.toNode | ||
|
||
of SymbolicName: | ||
curr.symbolicName = i.val.s | ||
of Constraint: | ||
let s = i.val.s | ||
if s[0] != '"' or s[^1] != '"': | ||
raiseAssert "constraint must be started and ended by " & '"' | ||
curr.constraint = s[1..^2] | ||
of InjectExpr: | ||
# only one inject expr for now | ||
curr.injectExpr = i.val.toNode | ||
|
||
of Clobber: | ||
let s = i.val.s | ||
if s[0] != '"' or s[^1] != '"': | ||
raiseAssert "clobber must be started and ended by " & '"' | ||
curr.clobber = s[1..^2] | ||
|
||
oldSec = i.sec |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is a EmitTarget an opcode of its own? We have a pragma annotation system in place for this...