forked from scala/scala
-
Notifications
You must be signed in to change notification settings - Fork 6
/
README.llvm
76 lines (59 loc) · 2.22 KB
/
README.llvm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
Instructions
------------
1. Run autoreconf
2. Run ./configure
3. Build scala with ant
4. Enter docs/examples/llvm
5. Run make run-sample
There's an example in docs/examples/llvm/ that can be compiled and run by
running 'make run-sample' in that directory. For comparison, you can run
'make run-sample-jvm' to compile and run for the JVM.
What's done
-----------
* Model for generating LLVM assembly
* Basic code generation
* Boxing/unboxing
* Conditional branches
* Unconditional branches
* Static method dispatch
* Loading constants
* Local variables load and store
* Fields load and store
* Primitive operations
* Instance creation
* Dynamic method dispatch
* Exceptions
What's not
----------
* Separate compilation
* Garbage collection
* Structural types
* Safety
* Array bounds checking
* ... ?
Points of Interest
------------------
Model for generating LLVM assembly is in src/llvm
The runtime library is partly written in scala
(docs/examples/llvm/runtime.scala) and partly in C (src/llvmrt)
Only new files in compiler are
src/compiler/scala/tools/nsc/backend/{LLVMPlatform.scala,llvm/GenLLVM.scala}
Everything interesting is in
src/compiler/scala/tools/nsc/backend/llvm/GenLLVM.scala
genClass writes out the LLVM assembly for each class. Lots of internal
functions do most of the work.
recordType, externModule, externFun, externClass record types, modules,
functions and class record that were used so the appropriate declarations can
be emitted
classInfo defines the class record which includes the class name, instance size
and super class pointer
moduleInfo defines the singleton instance and initializer
genFun generates the code for each method in the class. Each basic block is
translated from ICode to LLVM instructions. A stack is used as instructions are
generated to map from ICode stack positions to LLVM registers. Each basic block
is analyzed (see stackUsage method) to see how many values it consumes from the
stack and how many are produced. The outputs are given well defined register
names so that the phi instructions at the start of the block can select the
right value for each predecessor block.
There are a bunch of methods for translating from scalac symbols and types to
the appopriate LLVM type.