Skip to content
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

WIP: a re-implementation of the compiler backend #424

Closed
wants to merge 396 commits into from
Closed
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
396 commits
Select commit Hold shift + click to select a range
a0868ac
irpasses: implement array-literal -> const lifting pass
zerbina Aug 17, 2022
5dfd733
irpasses: progress on `set`-op lowering
zerbina Aug 17, 2022
1bba94a
irgen: implement `irNull` via `mDefault`
zerbina Aug 17, 2022
feea419
irpasses: implement `mDefault` transform
zerbina Aug 17, 2022
bbae099
irdbg: print the type for type-literals
zerbina Aug 17, 2022
6dee9e7
cgen2: implement object down-conversion
zerbina Aug 17, 2022
977277c
irgen: transform `mInc`/`mDec`
zerbina Aug 17, 2022
aff3717
cgen2: emit `bcError` in the generated code
zerbina Aug 17, 2022
518a92d
irgen: store the discriminator symbol position instead
zerbina Aug 17, 2022
c3e03ef
cbackend2: fix `importc` fix being unreliable
zerbina Aug 17, 2022
3f19907
cbackend2: store the IR for all procedures in a single `seq`
zerbina Aug 29, 2022
c5b95a5
introduce the `ModuleData` type
zerbina Aug 29, 2022
ae116d1
cgen2: replace usages of `IrStore3.owner`
zerbina Aug 29, 2022
03a51f7
cgen2: translate more magics
zerbina Aug 29, 2022
c857822
cgen2: fix wrong `min`/`max` implementation
zerbina Aug 29, 2022
499f06b
irgen: don't exclude `skForVar`s from being globals
zerbina Aug 29, 2022
914c37f
cgen2: emit definitions for globals
zerbina Aug 29, 2022
f18dfb6
cbackend2: register alive globals to modules
zerbina Aug 29, 2022
cc9f806
irgen: fix stack-overflow in compiled code
zerbina Aug 29, 2022
60da39c
irgen: fix inverted branch conditions
zerbina Aug 29, 2022
c3a9dfa
cbackend2: register lifted RTTI globals
zerbina Aug 29, 2022
314f59d
irpasses: move more utility procs to `pass_helpers`
zerbina Aug 29, 2022
9c6f440
move RTTI related processing logic into a dedicated module
zerbina Aug 29, 2022
7c54b59
vmir: better support for compiler-generated magic calls (part 1)
zerbina Aug 29, 2022
0b0e26c
vmir: better support for compiler-generated magic calls (part 2)
zerbina Aug 29, 2022
e490f16
vmir: better support for compiler-generated magic calls (part 3)
zerbina Aug 29, 2022
a18f950
cgen2: emit definitions for constants
zerbina Aug 29, 2022
db05987
irtypes: correctly handle generic object types
zerbina Aug 29, 2022
3ff79aa
irgen: pass the original type for `nkNilLit`
zerbina Aug 29, 2022
6a73f44
irgen: correctly omit compile-time-only arguments
zerbina Aug 29, 2022
8ea6a71
cgen2: remove stale string-literal handling
zerbina Aug 29, 2022
e019d91
irgen: lower `mHigh`
zerbina Aug 29, 2022
d4a1d43
irgen: fix `sizeof` for incomplete types
zerbina Aug 29, 2022
1c4e795
irgen: fix exception matching IR generation
zerbina Aug 29, 2022
8a04e43
irgen: manually translate `mOf`
zerbina Aug 29, 2022
8f78a25
irpasses: first version of `mOf` lowering
zerbina Aug 29, 2022
7656985
type-field support (part 1)
zerbina Aug 30, 2022
bbc0bbc
type-field support (part 2)
zerbina Aug 30, 2022
0b5b30f
type-field support (part 3)
zerbina Aug 30, 2022
10231d6
type-field support (part 4)
zerbina Aug 30, 2022
e0f9475
type-field support (part 5)
zerbina Aug 30, 2022
efaa12a
cgen2: map each field index to an identifier
zerbina Aug 30, 2022
a4f845d
irtypes: introduce `DeclarationV2` entities in `SymbolEnv`
zerbina Aug 30, 2022
2ba22f9
irtypes: don't use `Symbol` for fields
zerbina Aug 30, 2022
c233fac
cbackend2: improve `generateTopLevelStmts`
zerbina Aug 30, 2022
609001c
irtypes: implement and use deferred translation for symbols
zerbina Aug 30, 2022
e8772a5
cgen2: don't require the existence of a 'result' identifier
zerbina Aug 30, 2022
836c989
cgen2: collect C-header dependencies from globals and constants
zerbina Aug 30, 2022
1a49d0d
cgen2: respect `.nodecl` for globals and constants
zerbina Aug 30, 2022
4a72dbf
irtypes: properly initialize declarations and symbols
zerbina Aug 30, 2022
6d66965
irpasses: fix issue with `set` literal -> uint translation
zerbina Aug 30, 2022
7606896
implement alive analysis for compilerprocs/type-attached ops
zerbina Aug 30, 2022
013342a
prevent multiple `TNimType` `.compilerproc` types
zerbina Aug 30, 2022
64db0b7
vmir: use a dedicated type for storing information about locals
zerbina Aug 30, 2022
7e2831c
irgen: respect `sfNoInit` for locals
zerbina Aug 30, 2022
fa66d05
vmir: rename `bcOf` to `bcMatch`
zerbina Aug 30, 2022
1f6fb1c
irpasses: add `TypedPassCtx`
zerbina Aug 30, 2022
dcfcfec
cpasses: implement `bcMatch` lowering
zerbina Aug 30, 2022
efacf5e
cbackend2: scan the bodies of constants for routines
zerbina Aug 30, 2022
2a4cf33
cgen2: fix string literals
zerbina Aug 30, 2022
2ca6ce8
cgen2: character literal support
zerbina Aug 30, 2022
155d953
cgen2: support all integer literals
zerbina Aug 30, 2022
8dbeff2
cgen2: fix issue with `cnkIntLit`
zerbina Aug 30, 2022
45ae9d3
cgen2: implement support for float-literals
zerbina Aug 30, 2022
1909e3d
cgen2: translation for more magics
zerbina Aug 30, 2022
72f1f1d
cpasses/cgen2: lower `mEqProc`
zerbina Aug 30, 2022
d75b165
cpasses: lower `mLtStr` and `mLeStr`
zerbina Aug 30, 2022
0c501b1
cpasses: lower `mLengthStr` for cstrings
zerbina Aug 30, 2022
e6a13a9
cgen2: translate `mAbsI`, `mChr`, and `mOrd`
zerbina Aug 30, 2022
ade5501
cgen2: handle `nkRStrLit` and `nkTripleStrLit`
zerbina Aug 30, 2022
1e618b4
irpasses: lower `mArrToSeq`
zerbina Aug 30, 2022
24c2db7
compiler-magic handling follow-up (part 1)
zerbina Aug 30, 2022
29fe6bd
compiler-magic handling follow-up (part 2)
zerbina Aug 30, 2022
3bc591e
compiler-magic handling follow-up (part 3)
zerbina Aug 30, 2022
077c2dc
cbackend2: set the `magicPredicate` for `TCtx`
zerbina Aug 30, 2022
b73fe6f
irpasses: implement lowering of the remaining `set` ops
zerbina Aug 30, 2022
c419c69
move unused/obsolete code to the new `staging` module
zerbina Aug 30, 2022
eb2c343
Sketch the next iteration of `IrNode`
zerbina Aug 30, 2022
3843c44
irpasses: remove unused `nthField`
zerbina Sep 5, 2022
0fcec01
vmir: implement a new approach for collecting...
zerbina Sep 5, 2022
bb014cb
irpasses: add `runPass2`
zerbina Sep 5, 2022
f56070f
cbackend2/cpasses: use batch-processing for passes
zerbina Sep 5, 2022
fca5b55
irgen: pre-transform `mOffsetOf`
zerbina Sep 5, 2022
f5b6d76
irgen: respect `.noinit` for return values
zerbina Sep 5, 2022
7f3d9f9
irgen: fix inverted branch condition in `genCase`
zerbina Sep 5, 2022
913ac67
irgen: default-initialize temporaries for now
zerbina Sep 5, 2022
39e84b7
irgen: treat string-literals without a type as a `tyString`
zerbina Sep 5, 2022
340ee4c
irpasses: add `genForLoop` helper template
zerbina Sep 5, 2022
6466927
irpasses: fix `mEqSet` transformation
zerbina Sep 5, 2022
a62de6a
irpasses: replace the manual for-loops in `genSetOp` with `genForLoop`
zerbina Sep 5, 2022
a4ab80e
irpasses: replace the manual for-loop in `lowerSeqsV1` with `genForLoop`
zerbina Sep 5, 2022
062f4bf
irtypes: introduce `RecordIter`
zerbina Sep 5, 2022
4688bd6
cgen2: transform `mOffsetOf`
zerbina Sep 5, 2022
a30a08b
cgen2: use `RecordIter`
zerbina Sep 5, 2022
f51d264
cgen2: support `genLit` in builder chains
zerbina Sep 6, 2022
ce3af59
irpasses: transform access to `seq|string` constants
zerbina Sep 6, 2022
da6d23a
cgen2: fix string literals (again)
zerbina Sep 6, 2022
d391d64
irtypes: export `fieldOffset`
zerbina Sep 6, 2022
d0ba87a
working prototype implementation for constants (part 1)
zerbina Sep 7, 2022
47c535e
working prototype implementation for constants (part 2)
zerbina Sep 7, 2022
06eb081
working prototype implementation for constants (part 3)
zerbina Sep 7, 2022
0f9a6be
working prototype implementation for constants (part 4)
zerbina Sep 7, 2022
e4e9539
working prototype implementation for constants (part 5)
zerbina Sep 7, 2022
92c5231
working prototype implementation for constants (part 6)
zerbina Sep 7, 2022
6072648
irpasses: transform large `set`-literals in one place
zerbina Sep 7, 2022
0eae980
cgen2: use an enum to refer to C operators
zerbina Sep 7, 2022
e502783
cgen2: use a lookup table for `COperator` -> string conversion
zerbina Sep 7, 2022
fd02360
irpasses: fix issue with `mAppendSeqElem` lowering
zerbina Sep 7, 2022
6e729dd
irpasses: refactor `mEqStr` lowering implementation
zerbina Sep 7, 2022
bf7e422
introduce a dedicated IR for literal data
zerbina Sep 9, 2022
931e011
irpasses: use immutable `LiteralData` object during lifting
zerbina Sep 9, 2022
4347053
cgen2: move dependency collection out of `genConstInitializer`
zerbina Sep 9, 2022
552e9fc
irpasses: use a cache for constants
zerbina Sep 9, 2022
28f4aea
use `LiteralId` + `LiteralData` for all literals
zerbina Sep 9, 2022
2d48ac4
vmir: store `Literal`s as part of `IrNode3`
zerbina Sep 9, 2022
7c7c7f7
cgen2: escape chars in strings with octal escape sequences
zerbina Sep 29, 2022
25a678b
cgen2: replace leftover `cnkIdent` usage for C operator tokens
zerbina Sep 29, 2022
d2d4350
cgen2: clean up constant initializer generation a bit
zerbina Sep 29, 2022
55f8e3c
cgen2: don't depend on C extensions for static initalizers
zerbina Sep 29, 2022
1c89e39
vmir: remove stale code-IR node kinds
zerbina Sep 29, 2022
45fae32
vmir: add a `[]` overload for `IrStore3`
zerbina Sep 29, 2022
a4912fb
cgen2: make sure the output adheres to the code-IR's semantics
zerbina Sep 29, 2022
6677748
irgen: remove outdated usages of `ntkUse`
zerbina Sep 29, 2022
0b4ebdb
vmir: fix branch targets not being patched
zerbina Sep 29, 2022
b0b6142
vmir: remove the `bcNew` built-in
zerbina Sep 29, 2022
ae7bf28
irgen: translate `string` <-> `cstring` conversions
zerbina Sep 29, 2022
5a79801
cbackend2: also collect `.compilerproc` globals and consts
zerbina Sep 29, 2022
c959475
cbackend2: simplify the test for imperative nodes
zerbina Sep 29, 2022
78985cc
cbackend2: use the modules' real ID instead of...
zerbina Sep 29, 2022
833dfb3
cbackend2: reorganize how module-related data is stored
zerbina Sep 29, 2022
cd72d8e
cbackend2: fix `.compilerproc`s being part of the...
zerbina Sep 29, 2022
b7a9c0f
irgen: handle `lfImportCompilerProc` for procedures
zerbina Sep 29, 2022
ad19c3a
cpasses: fix critical typo
zerbina Sep 29, 2022
ba91ae4
cpasses: temporary fix for `mParseBiggestFloat`
zerbina Sep 29, 2022
d0f8820
cbackend2: implement 'main' procedure generation
zerbina Sep 29, 2022
0530833
irpasses: improve `mDefault` lowering implementation
zerbina Sep 29, 2022
028ba27
vmir: fix error with `moveMem` if `len == 0`
zerbina Sep 29, 2022
675f2eb
cbackend2: free the `TCtx` object when it's no longer needed
zerbina Sep 29, 2022
22fe381
cgen2: support 'nil' literals of `cstring` type
zerbina Sep 29, 2022
717c6df
irtypes: implement the `fields` iterator
zerbina Sep 29, 2022
7590337
cbackend2: compute the type-field status for all types
zerbina Sep 29, 2022
b6e6176
irpasses: don't transform access to globals in `liftSeqConstsV1`
zerbina Sep 29, 2022
fe2dc10
[bugfix] irpasses: properly lower `mSetLength(Str|Seq)`
zerbina Sep 29, 2022
7fb1558
irpasses: fix `genRefcRefAssign`
zerbina Sep 29, 2022
bf20f71
irtypes: remove `tnkName`
zerbina Sep 29, 2022
8ee3ef8
cpasses: lower `mAccessEnv`
zerbina Sep 29, 2022
1414c5e
add the `bitsetutils` module
zerbina Sep 29, 2022
25c9011
add the `computeGcLookup` procedure
zerbina Sep 29, 2022
c324d0e
irpasses: properly lower assignments for `refc`
zerbina Sep 29, 2022
abe143a
vmir: remove some leftover debug logic
zerbina Sep 29, 2022
fc62829
cbackend2: remove unneeded copy
zerbina Sep 29, 2022
6a88fab
irtypes: fix evaluation order issue in `translateAux`
zerbina Sep 29, 2022
ae28922
irpasses: allow applying a type map during type computation
zerbina Sep 29, 2022
8d87705
irpasses: clean-up the `RefcPassCtx` type
zerbina Sep 29, 2022
4085ab7
irpasses: make the `openArray` code lowering pass...
zerbina Sep 29, 2022
52bdf39
add new pass type
zerbina Sep 29, 2022
00e373a
use `TypeContext` in `RefcPassCtx`
zerbina Sep 29, 2022
ead64c4
refactor how passes with access to type information work (part 3)
zerbina Sep 29, 2022
49d1ad9
refactor how passes with access to type information work (part 4)
zerbina Sep 29, 2022
bad040a
refactor how passes with access to type information work (part 5)
zerbina Sep 29, 2022
0f3e398
refactor how passes with access to type information work (part 6)
zerbina Sep 29, 2022
49fdcc9
refactor how passes with access to type information work (part 7)
zerbina Sep 29, 2022
d582ef6
refactor how passes with access to type information work (part 8)
zerbina Sep 29, 2022
7a477ea
refactor how passes with access to type information work (part 9)
zerbina Sep 29, 2022
f5d9319
follow up: remove `TypedPassCtx`
zerbina Sep 29, 2022
a2d5b3d
cbackend2: run `hookPass` and `lowerMatchPass` in the same batch
zerbina Sep 29, 2022
b19b7ff
irpasses: treat `askInit` as `askCopy` for now
zerbina Sep 29, 2022
74592e8
apply the `seq` transform pass before the GC pass (part 1)
zerbina Sep 29, 2022
7978271
apply the `seq` transform pass before the GC pass (part 2)
zerbina Sep 29, 2022
8b79af7
apply the `seq` transform pass before the GC pass (part 3)
zerbina Sep 29, 2022
6e78fd4
add a temporary directory for tests
zerbina Sep 29, 2022
6577919
irpasses: fix `mInSet` implementation
zerbina Sep 29, 2022
904e7c8
irpasses: fix `mSetLengthSeq` implementation
zerbina Sep 29, 2022
8b263ea
vmir: use half-open ranges for changed regions
zerbina Sep 29, 2022
40a81bd
irpasses: lower `mWasMoved` for GC'ed locations
zerbina Sep 29, 2022
03462ff
irgen: properly handle `mMove`
zerbina Sep 29, 2022
7299dee
irgen: catch-all translation for `mMove`
zerbina Sep 29, 2022
180bb67
vmir: introduce `bcInitLoc`
zerbina Sep 29, 2022
bb67b1b
vmir: introduce `bcFinishConstr`
zerbina Sep 29, 2022
1be7cbf
irpasses: fix initializing assignments for complex data
zerbina Sep 29, 2022
915d544
further progress on assignment handling
zerbina Sep 29, 2022
e53628f
irtypes: support translation of closure literals
zerbina Sep 29, 2022
66bf823
irpasses: fix issues with `genForLoop`
zerbina Sep 29, 2022
8d280ba
irpasses: fix `genNewObj`
zerbina Sep 29, 2022
b7f15a8
irpasses: remove the `mDestroy` lowering
zerbina Sep 29, 2022
5894b6c
irpasses: fix the `mAppendStrStr` lowering
zerbina Sep 29, 2022
5e87e15
irgen: fix the `mSwap` translation
zerbina Sep 29, 2022
efec736
cgen2: make sure literals have the correct type
zerbina Sep 29, 2022
a0a4f0b
irgen: fix the static exception name being passed...
zerbina Sep 29, 2022
bfa22f7
irpasses: add missing `replace` call
zerbina Sep 29, 2022
ae9b444
irpasses: properly lower `mAppendSeqElem`
zerbina Sep 29, 2022
b6c2930
vmir: add `pairs` iterator for `IrStore3`
zerbina Sep 29, 2022
49bc9e2
irpasses: implement `StorageLoc` computation
zerbina Sep 29, 2022
ef71ced
irgen: use `unreachable` for unsupported `PNode` kinds
zerbina Sep 29, 2022
422ad5a
irpasses: fix overflow-checks being generated even if disabled
zerbina Sep 29, 2022
0c07db4
cpasses: split off the closure transform logic from `applyCTransforms`
zerbina Sep 29, 2022
7206d19
cpasses: remove `applyCTransforms`
zerbina Sep 29, 2022
3bb6764
vmir: implement `ntkLocEnd`
zerbina Sep 29, 2022
964d628
vmir: implement `ntkGotoLink`
zerbina Sep 29, 2022
84e0d82
cgen2: handle `ntkLocEnd`
zerbina Sep 29, 2022
3d58308
irgen: fix a wrong usage of `ntkBranch`
zerbina Sep 29, 2022
a0daead
vmir: add `bcNone`
zerbina Sep 29, 2022
883e08b
working exception handling (part 1)
zerbina Sep 29, 2022
2cb46a2
working exception handling (part 2)
zerbina Sep 29, 2022
441c342
cpasses: lower `ntkGotoLink` and `ntkContinue`
zerbina Sep 29, 2022
599f53f
cbackend2: report unhandled exceptions
zerbina Sep 29, 2022
c7edf74
system/excpt: fix `nimTestErrorFlag` doing nothing
zerbina Sep 29, 2022
3bcd935
irpasses: fix issue due to missing type
zerbina Sep 29, 2022
c7b130d
irpasses: fix inverted condition in `genSubsetRelOp`
zerbina Sep 29, 2022
92fb76d
irgen: mirror the `mInSet` semantics used by `cgen`
zerbina Sep 29, 2022
0dd708e
irgen: account for sets with `firstOrd != 0`
zerbina Sep 29, 2022
851379c
irgen: remove emit of unused temporary
zerbina Sep 29, 2022
9289d01
cgen2: support unlowered `mOr` magics
zerbina Sep 29, 2022
f1b45a7
irpasses: finish the range-check lowering implementation
zerbina Sep 29, 2022
f3708a5
irpasses: fix off-by-one error with `mSlice` length
zerbina Sep 29, 2022
c17507b
cpasses: don't introduce a temporary for same-type conversions
zerbina Sep 29, 2022
f33915e
irgen: temporarily remove usage of `bcGetBranchIndex`
zerbina Sep 29, 2022
24a4349
irtypes: hide `RecordNode` implementation details
zerbina Sep 29, 2022
b9c8e42
irtypes: use a canonical representation for empty records
zerbina Sep 29, 2022
cdea0e6
irtypes: fix field sections being erroneously merged
zerbina Sep 29, 2022
9f05c90
irpasses: properly handle GC'ed types used with `askMove`
zerbina Sep 29, 2022
d52ea4b
cgen2: use `unsafeAddr` instead of `addr`...
zerbina Sep 29, 2022
ea353a9
cgen2: add sanity check
zerbina Sep 29, 2022
d340f0b
cgen2: don't use `mangledName` for imported types
zerbina Sep 29, 2022
14bf521
cgen2: use '"' if no include syntax is specified...
zerbina Sep 29, 2022
0d0db1d
cgen2: work around C type incompatibility
zerbina Sep 29, 2022
e871798
irtypes/cgen2: support `.union`
zerbina Sep 29, 2022
157f33f
cgen2: use `NU8` as the C type for `char`
zerbina Sep 29, 2022
95cac5e
irpasses: use a `set` for the type-field status
zerbina Sep 29, 2022
78ea63f
cbackend2: pass a procedure's options to `irgen`
zerbina Sep 29, 2022
2b5382e
cbackend2: small refactor
zerbina Sep 29, 2022
5e2326c
cbackend2: remove `newPassEnv`
zerbina Sep 29, 2022
204639f
irtypes: implement `RecordNode` attachements
zerbina Sep 29, 2022
54bc343
implement marker procedure generation
zerbina Sep 29, 2022
87e6bab
cgen2: support unnamed procedure parameters
zerbina Sep 29, 2022
7895bb7
cpasses: make the matcher code generation logic...
zerbina Sep 29, 2022
a1d1ea3
irdbg: fix issue with `typeToStr`
zerbina Sep 29, 2022
a3da2b5
finish the compiler-to-runtime type interface
zerbina Sep 29, 2022
11bd821
add additional tests
zerbina Sep 29, 2022
8ebdfa9
cgen2: prevent identifiers clashing with...
zerbina Sep 29, 2022
ad33ad9
cgen2: cleanup
zerbina Sep 29, 2022
d4d316e
vmir: update comments
zerbina Sep 29, 2022
a1b3592
cbackend2: cleanup
zerbina Sep 29, 2022
bb77827
cpasses: improve comments
zerbina Sep 29, 2022
f93be5b
irpasses: cleanup
zerbina Sep 29, 2022
5e20453
irtypes: cleanup
zerbina Sep 29, 2022
7dba161
irgen: cleanup
zerbina Sep 29, 2022
b5b9cd4
testament: enable the new back-end for the C target
zerbina Oct 2, 2022
6639bee
Merge branch 'devel' into backend-ir
zerbina Oct 2, 2022
8cffc58
irgen: adjust to upstream changes
zerbina Oct 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/ast/nimsets.nim
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ proc someInSet*(s: PNode, a, b: PNode): bool =

proc inclTreeSet*(result: var TBitSetView, conf: ConfigRef; s: PNode) =
## Includes all elements from tree-set `s` into `result`
assert result.len == int(getSize(conf, s.typ))
# XXX: requiring the length to fit might help in catching some issues, but
# it's too restrictive
assert result.len >= int(getSize(conf, s.typ))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it instead introduce a new proc that is relaxed while keeping it strict elsewhere?

var first, j: Int128
first = firstOrd(conf, s.typ[0])
for i in 0..<s.len:
Expand Down
11 changes: 9 additions & 2 deletions compiler/front/main.nim
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ import compiler/ic/[
]
from compiler/ic/ic import rodViewer

from compiler/vm/cbackend2 import nil

when not defined(leanCompiler):
import
compiler/backend/jsgen,
Expand Down Expand Up @@ -146,22 +148,27 @@ proc commandCompileToC(graph: ModuleGraph) =
let conf = graph.config
extccomp.initVars(conf)
semanticPasses(graph)
if conf.symbolFiles == disabledSf:
if conf.symbolFiles == disabledSf and not isDefined(graph.config, "cbackend2"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be flipped to

if isDefined(graph.config, "cbackend2"): ...
elif conf.symbolFiles == disabledSf: ...

as you did in line 169.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's cleaner, thanks.

registerPass(graph, cgenPass)

if {optRun, optForceFullMake} * conf.globalOptions == {optRun} or isDefined(conf, "nimBetterRun"):
if not changeDetectedViaJsonBuildInstructions(conf, conf.jsonBuildInstructionsFile):
# nothing changed
graph.config.notes = graph.config.mainPackageNotes
return
else:
graph.config.exc = excGoto # only goto exceptions are support for the new cbackend
Copy link
Collaborator

@saem saem Oct 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking out loud, a smaller PR we could pull out of this one is removing the other exception types.

registerPass(graph, cbackend2.cgen2Pass)

if not extccomp.ccHasSaneOverflow(conf):
conf.defineSymbol("nimEmulateOverflowChecks")

compileProject(graph)
if graph.config.errorCounter > 0:
return # issue #9933
if conf.symbolFiles == disabledSf:
if isDefined(graph.config, "cbackend2"):
cbackend2.generateCode(graph)
elif conf.symbolFiles == disabledSf:
cgenWriteModules(graph.backend, conf)
else:
if isDefined(conf, "nimIcIntegrityChecks"):
Expand Down
12 changes: 6 additions & 6 deletions compiler/sem/sighashes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ type
CoDistinct
CoHashTypeInsideNode

proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag])
func hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read this file, then thought:

🎶 won't you take me to... Func-y town🎶 😁


proc hashSym(c: var MD5Context, s: PSym) =
func hashSym(c: var MD5Context, s: PSym) =
if sfAnon in s.flags or s.kind == skGenericParam:
c &= ":anon"
else:
Expand All @@ -63,7 +63,7 @@ proc hashSym(c: var MD5Context, s: PSym) =
c &= "."
it = it.owner

proc hashTypeSym(c: var MD5Context, s: PSym) =
func hashTypeSym(c: var MD5Context, s: PSym) =
if sfAnon in s.flags or s.kind == skGenericParam:
c &= ":anon"
else:
Expand All @@ -76,7 +76,7 @@ proc hashTypeSym(c: var MD5Context, s: PSym) =
c &= "."
it = it.owner

proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
func hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
if n == nil:
c &= "\255"
return
Expand All @@ -103,7 +103,7 @@ proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
else:
for i in 0..<n.len: hashTree(c, n[i], flags)

proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
func hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
if t == nil:
c &= "\254"
return
Expand Down Expand Up @@ -265,7 +265,7 @@ when defined(debugSigHashes):
# select hash, type from sighashes where hash in
# (select hash from sighashes group by hash having count(*) > 1) order by hash;

proc hashType*(t: PType; flags: set[ConsiderFlag] = {CoType}): SigHash =
func hashType*(t: PType; flags: set[ConsiderFlag] = {CoType}): SigHash =
var c: MD5Context
md5Init c
hashType c, t, flags+{CoOwnerSig}
Expand Down
170 changes: 170 additions & 0 deletions compiler/vm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@

All of the IR related work is currently located in the `vm` directory, since the IR originally started out as an IR for only the VM.

Things to consider when reading the code:
* more or less everything is still a work in progress
* there's a lot of debug code lying around
* there's lots of outdated and stale code
* most outdated or unfinished parts aren't marked as such
* most of the existing documentation is unfinished or outdated
* some comments (general ones, `XXX` and `TODO`) are outdated and don't apply anymore

The general approach for the new compiler backend is the following:
* take the `PNode`-AST that comes out of `transf` and translate it into a dedicated intermediate representation used until code generation
* apply transformations not specific to a target to the IR
* apply target-specific transformations to the IR
* pass the IR to the target's code-generator

Some future directions and missing pieces are also documented here, but not all of them.

## Overview of the added modules

### `vmir.nim`

The module still has it's original name, but the IR is fully decoupled from the VM. A lot of old code from previous iterations is in here.

The relevant parts are:
* `IrNode3`: the type of the IR's node structure. Currently a variant object, but planned to move to a more generalized representation.
* `IrStore3`: stores the nodes together with the extra data needed (referenced symbols, join target, etc.). Generally refered to as **the** IR. A simple mechanism for tracking where in the compiler each `IrNode3` was added (or modified). This currently just uses stack-traces, but is planned to be expanded into a more proper facility to track node modifications.
* `BuiltinCall`: meant as an extension to magics, except that they're only needed in the backend. Introduced in order to not require changes to the `TMagic` enum.
* `IrCursor`: API to modify the IR. It first records all modifications and then applies them. Not very efficient right now. This might replace the older `irXXX`-procedure based IR generation (I'm not sure yet)

Other parts:
* `genCodeV3Exec`: a very early prototype of a code-generator for the VM, taking the IR as input and producing VM bytecode
* `IrStore`, `IrNode2`: old attempts at the IR. Still kept around since there are some parts that might be reused
* `computeInlining`: an early, non-working prototype of computing the most memory efficient IR generation order in the context of procedure inlining

#### IR overview:
* the IR is a linear node-based representation
* nodes reference each other via indices. A node can only reference nodes coming before it; reference cycles are forbidden
* it's still undecided if a node may be referenced multiple times
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within the AST proper, no.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do see this as useful for something like the empty node, but I'm not convinced if this is the right thing.

* control-flow is represented via gotos and joins. Instead of storing the index of the corresponding `join` target, a `goto` stores an index (`JoinPoint`) into a list storing the actual IR indices. This is aimed at making IR modification simpler, by removing the need to patch goto targets in the IR directly.
* there exist a few special experimental gotos (goto-link-back, goto-with-continuation, goto-active-continuation) meant for more efficient `finally` handling
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Philosophical remark:

This feels like a theme in my experience.

It starts with a very small set of core primitives that are beautiful and all, great for learning and conveying key concepts. Then for making them actually useful a large set of variants are then introduced to encode constraints information.

* the implementation is currently not very data-oriented, but the plan is to move it there eventually.


### `irgen.nim`

A heavily modified copy of `vmgen.nim`. Takes a post-`transf` procedure's `PNode`-AST as the input and translates it to the IR. Traverses the input AST and emits IR instructions via the various `irXXX` procedures.

`irXXX` procedures defined in `irgen` are experimental and don't have a corresponding IR instruction (yet), but use a combination of other IR instructions.

### `irpasses.nim`

Implements the existing IR transformations. This currently includes general transformations as well as target specific ones. The target-specific passes will be moved to their own modules later on. Most transformations are exposed via the `LinearPass` interface.

None of existing passes are finished yet.

`runV2` implements the base for static-control-flow-based analysis (e.g. alias analysis, last-read-write analysis, escape analysis, etc.).

An overview of the current passes:

#### `computeAliases`

Old, unused, and defunct early prototype of the alias analysis.

#### `computeDestructors`

Old, unused, and defunct early prototype of the destructor injection pass.

#### `hookPass`

Meant to replace assignments and `mDestroy` calls with calls to the `=copy`, `=sink` and `=destroy` hooks (if they are present). This is a general pass that applies to all targets and garbage collectors.

Introduced before `LinearPass2` existed and is thus missing the `mDestroy` patching.

Currently also ignores whether or not a hook is trivial and thus replaces the assignment for types that don't actually need/use a `=copy` hook.

#### `refcPass`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly another PR, we drop refc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As refc support is fully implemented already, I'd be a bit reluctant to remove it either before or as part of this PR and instead would rather remove it after. The implementation is then preserved in the git history at least.

One thing to consider is that the refc, markAndSweep, boehm, and go GC support share almost all of their implementation in the compiler, so only removing refc would not reduce (by a significant amount) the required code/complexity.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, ok we don't have to do it just yet.

As for the other GCs I would drop all of those as well.


Used when the `refc` GC is enabled. Transforms `ref` (and erroneously also `seq` and `string`) assignments; lifts GC visit procs; lowers `new`, etc

The GC visit procedure lifting is not yet implemented.

Doing the lifting in a separate pass would allow for the `refcPass` to also be applicable to the `markAndSweep` and `boehm` GCs. With some additional adjustments the `go` could also be included in that list.

#### `seqsV1Pass`

Lowers `seq`s to `PGenericSeq` based operations. Meant for the C-like targets and used when `optSeqDestructors` (implied by ARC/ORC) is not enabled.

All references to `seq` types need to be rewritten to use the `PGenericSeq` based type. Since seqs are generic, the new types need to be created as part of the pass (implemented).

The types of locals, globals an parametes are currently adjusted (in a rather in-elegant manner), but field types also need to adjusted! This is not easily doable with the current surrounding architecture and a rewrite of how the types are adjusted is planned.

A better approach for the type rewriting part would be to introduce a new kind of pass that operates only on types. `cbackend2` is then responsible for collecting all used types (this makes sense in general). The types could then also be run through a unification step, since most of the time, multiple `PType` instances exist for the exact same type (the VM also does this unification).

As a further improvement, the IR should use it's own representation of types and symbols (a very early prototype exists in `irtypes.nim`).

#### `seqsV2Pass`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another PR possibility, we drop one off these and only support one. It doesn't have to be 2, we can just have one that's most convenient and then upgrade that to one we want.


Same as `seqsV1Pass`, but uses `NimSeqV2`. Also meant for the C-like targets and used when `optSeqDestructors` is enabled.


#### `typeV1Pass`

Creates globals to hold the used RTTI and also generates their initialization logic. Transforms usage of `mGetTypeInfo` to use the introduced globals. Meant for the C-like and JS targets.

The initialization logic generation is not implemented yet.


#### `lowerTestError`

Injects the pieces necessary for the `exceptions:goto` implementation on the C-like and JS targets. Not needed for the VM.

#### `lowerRangeCheckPass`

Transforms `bcRangeCheck` (coming from `nkRangeChck`) into comparisons plus `raiseRangeErrorXXX` calls. Meant to be a general pass, applying to all targets (except maybe the VM, since it currently does the checks at the instruction level).

#### `lowerSetsPass`

Lowers `set` operations into bit operations on integers and arrays. Meant for the C-like targets.

The required replacing of `set` types is missing.

### `irtypes.nim`

Very early and not yet used prototype of a type representation for the backend.

Using a dedicated type (symbols too) representation for the backend stage would mean that `PType` (and `PSym`) no longer has to accomodate for backend specific needs.

It also allows for using a more linear, data-oriented approach for storing the types without having to adjust all of the compiler. Since the backend is written with a data-oriented approach in mind, it would greatly benefit from this.


### `cbackend2.nim`

A copy of `vmbacked.nim` with the VM related bits removed. Adjusted to use the IR and `cgen2`.

Points of interest:
* `generateCode`: orchestrates IR generation for all alive procedures (`method` handling is missing) and calls the code-generator (`cgen2`)

**Note**: the DCE implementation currently runs before any IR transformations took place and thus doesn't know about used compilerprocs and some magics.

Semantic analysis and backend processing happen separate from each other. That is, first the semantic analysis for the whole program is performed and only then is the backend executed.

Pros:
* makes it easier to reason about the compiler
* compilerprocs in `system.nim` can be declared in any order, since once the backend is reached, all of them are available
* whole-program optimizations become possible

Cons:
* higher memory usage, since the bodies of all semantically analysed procedures need to be kept alive until the backend stage
* errors occuring in the back-end are only reported much later (but these error should only be internal ones, this shouldn't be a problem in practice)

For what it's worth, the VM backend (`vmbackend`) and the `PackedNode`-based backend (`cbackend`) meant for IC both also use the approach described here.

The backend only supports running it against the whole program right now, but it's written in a way that makes it easy to support smaller, more granular working sets.

### `cgen2.nim`

The code-generator for the C target. It takes the IR for all procedures in a module, translates them to a simple AST, and then emits the latter to the given output file.

The first iteration concatenated strings together with the plan to move to an AST-based approach later on, but I quickly figured that doing the switch already would make thing much simpler (and it did!). Some remnants of the original approach are still visible however.

Types currently use their own IR in order to make the whole dependency discovery easier. I'd consider the whole approach to type handling here wrong however. Figuring out the order in which types need to be emitted is not a problem specific to the C target and should thus be done outside of the C code-generator (this is also what's planned).

Instead of always writing to a file, it might make sense to pass `emitModuleToFile` a `Stream` instead and let the caller decide on where the output should go.

Points of interest:
* `genCode`: translates the input IR to the simple C AST
* `genCTypeDecl`: translates `PType` to a `CDecl`
* `emitModuleToFile`: the main entry point into the code generator. Orchestrates the C AST and type declaration generation and then emits everything in the correct order.
40 changes: 40 additions & 0 deletions compiler/vm/bitsetutils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## This module implements bit-sets supporting an arbitrary amount of elements.
## The implementation is a thin, type-safe wrapper around
## ``compiler/utils/bitsets``.

# TODO: apply some polish (documentation, cleanup, etc.) and move this module
# to ``compiler/utils``

import compiler/utils/bitsets

export bitsets

type BitSet*[T: Ordinal] = object
data: TBitSet

func newBitSet*[T](_: typedesc[T], elems: Natural): BitSet[T] =
result.data.bitSetInit((elems + 7) div 8)

func incl*[T](x: var BitSet[T], elem: T) {.inline.} =
x.data.bitSetIncl(elem.BiggestInt)

func excl*[T](x: var BitSet[T], elem: T) {.inline.} =
x.data.bitSetExcl(elem.BiggestInt)

func contains*[T](x: BitSet[T], elem: T): bool {.inline.} =
x.data.bitSetIn(elem.BiggestInt)

func containsOrIncl*[T](x: BitSet[T], elem: T): bool {.inline.} =
result = elem in x
if not result:
x.incl elem

iterator items*[T](x: BitSet[T]): T =
var i = 0
let L = x.data.len * 8
while i < L:
let b = x.data[i shr 3]
if b shr (i and 7) != 0:
yield T(i)

inc i
Loading