Compare commits
5 Commits
db1eba08b8
...
feature/ne
| Author | SHA1 | Date | |
|---|---|---|---|
| d2abb6faa3 | |||
| ee0d649db8 | |||
| 100ddd9a87 | |||
| 89b9fbc988 | |||
| fb09facdda |
@@ -1,6 +1,62 @@
|
|||||||
BasedOnStyle: WebKit
|
BasedOnStyle: WebKit
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
---
|
---
|
||||||
|
Language: C
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Right
|
||||||
|
ColumnLimit: 80
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignConsecutiveBitFields: None
|
||||||
|
AlignConsecutiveDeclarations: None
|
||||||
|
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: AlignAfterOperator
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLambdasOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
BreakBeforeBinaryOperators: All
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakInheritanceList: BeforeComma
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
SortIncludes: true
|
||||||
|
IndentRequires: true
|
||||||
|
NamespaceIndentation: Inner
|
||||||
|
ReflowComments: true
|
||||||
|
SpacesBeforeTrailingComments: 3
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: AlignWithSpaces
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||||
|
PenaltyExcessCharacter: 5
|
||||||
|
PenaltyBreakOpenParenthesis: 5
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 5
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
AttributeMacros:
|
||||||
|
- BLUELIB_API
|
||||||
|
ForEachMacros:
|
||||||
|
- b_btree_foreach
|
||||||
|
- b_queue_foreach
|
||||||
|
---
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "mie"]
|
||||||
|
path = mie
|
||||||
|
url = https://g.wash.red/wash/mie.git
|
||||||
7
doc/mie-passes.txt
Normal file
7
doc/mie-passes.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
ivy.fold-int-constants
|
||||||
|
ivy.fold-pool-constants
|
||||||
|
ivy.expand-lambdas
|
||||||
|
ivy.convert-alloca-to-bp-slot
|
||||||
|
ivy.convert-string-builder-to-msg
|
||||||
|
scf.convert-to-cf
|
||||||
|
ivy.convert-to-cf
|
||||||
530
doc/mie/sample/Person.2.mie
Normal file
530
doc/mie/sample/Person.2.mie
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
meta.source-filename "Person.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder : ptr
|
||||||
|
|
||||||
|
ivy.class @Person {
|
||||||
|
%self.name = ivy.object-var @name : #ivy.id -> ptr
|
||||||
|
%self.age = ivy.object-var @age : #ivy.id -> ptr
|
||||||
|
%self.val = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
%self.__example-property-4 = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
%self.__example-property-5 = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
|
||||||
|
%lambda.0 = ivy.lambda.body <%env> (%i: #ivy.id) -> void {
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder -> ptr
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Count is "
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%i -> void
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %3, put:%2 -> void
|
||||||
|
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
%lambda.1 = ivy.lambda.body <%env> () -> void {
|
||||||
|
%env.q = ivy.pkg.get %env[@q] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder -> ptr
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Value of q is "
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%env.q -> void
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %3, put:%2 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method init(name:%name, age:%age) -> void {
|
||||||
|
ptr.store %name, %self.name : #ivy.id, ptr
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method test(param:%data, _:%extra) -> void {
|
||||||
|
%0 = ptr.load %StringBuilder : ptr -> #ivy.id
|
||||||
|
%1 = ivy.msg.send to %0, new -> #ivy.id
|
||||||
|
|
||||||
|
%2 = ivy.str.constant "Received "
|
||||||
|
ivy.msg.send to %1, append:%2 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %1, append:%data -> void
|
||||||
|
|
||||||
|
%3 = ivy.str.constant ", "
|
||||||
|
ivy.msg.send to %1, append:%3 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %1, append:%extra -> void
|
||||||
|
|
||||||
|
%4 = ivy.msg.send to %1, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%5 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %5, put:%4 -> void
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method name -> #ivy.id {
|
||||||
|
%0 = ptr.load %self.name : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method age -> #ivy.id {
|
||||||
|
%0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method age-in-months -> #ivy.id {
|
||||||
|
%0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%1 = i32.constant 12
|
||||||
|
%multmp = ivy.mul %0, %1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
func.return %multmp : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method set-name:%name -> void {
|
||||||
|
ptr.store %name, %self.name : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method set-age:%age -> void {
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method set-age:%age in-units:%units -> void {
|
||||||
|
^switch.cond.0:
|
||||||
|
%0 = ivy.atom "years"
|
||||||
|
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.0, ^switch.body.0, ^switch.cond.1
|
||||||
|
|
||||||
|
^switch.body.0:
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.cond.1:
|
||||||
|
%1 = ivy.atom "months"
|
||||||
|
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.1, ^switch.body.1, ^switch.cond.2
|
||||||
|
|
||||||
|
^switch.body.1:
|
||||||
|
%d0 = i32.constant 12
|
||||||
|
%divtmp.0 = ivy.div %age, %d0 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
ptr.store %divtmp.0, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.cond.2:
|
||||||
|
%2 = ivy.atom "days"
|
||||||
|
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.2, ^switch.body.2, ^switch.default
|
||||||
|
|
||||||
|
^switch.body.2:
|
||||||
|
%d1 = i32.constant 365
|
||||||
|
%divtmp.1 = ivy.div %age, %d1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
ptr.store %divtmp.1, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.default:
|
||||||
|
%d2 = i32.constant 0
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.end:
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.method get-age-in-units:%units -> #ivy.id {
|
||||||
|
^switch.cond.0:
|
||||||
|
%0 = ivy.atom "years"
|
||||||
|
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.0, ^switch.body.0, ^switch.cond.1
|
||||||
|
|
||||||
|
^switch.body.0:
|
||||||
|
%v0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
cf.br ^switch.end(%v0: #ivy.id)
|
||||||
|
|
||||||
|
^switch.cond.0:
|
||||||
|
%1 = ivy.atom "months"
|
||||||
|
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.1, ^switch.body.1, ^switch.cond.2
|
||||||
|
|
||||||
|
^switch.body.0:
|
||||||
|
%v0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%d0 = i32.constant 12
|
||||||
|
%divtmp.0 = ivy.div %v0, %d0 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
cf.br ^switch.end(%divtmp.0: #ivy.id)
|
||||||
|
|
||||||
|
^switch.cond.0:
|
||||||
|
%2 = ivy.atom "days"
|
||||||
|
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.2, ^switch.body.2, ^switch.default
|
||||||
|
|
||||||
|
^switch.body.0:
|
||||||
|
%v1 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%d1 = i32.constant 365
|
||||||
|
%divtmp.1 = ivy.div %v1, %d1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
cf.br ^switch.end(%divtmp.1: #ivy.id)
|
||||||
|
|
||||||
|
^switch.default:
|
||||||
|
%d2 = i32.constant 0
|
||||||
|
cf.br ^switch.end(%d2.1: i32)
|
||||||
|
|
||||||
|
^switch.end(%result: #ivy.id):
|
||||||
|
func.return %result : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property
|
||||||
|
get {
|
||||||
|
%0 = ptr.load %self.val : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
set (%value: #ivy.id) {
|
||||||
|
ptr.store %value, %self.val : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-2 get {
|
||||||
|
%0 = ptr.load %self.val : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
} set (%x: #ivy.id) {
|
||||||
|
ptr.store %x, %self.val : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-3 get {
|
||||||
|
%0 = i32.constant 42
|
||||||
|
func.return %0 : i32
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-4 get {
|
||||||
|
%0 = ptr.load %self.p-example-property-4 : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
} set (%0: #ivy.id) {
|
||||||
|
ptr.store %0, %self.p-example-property-4 : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-5 get {
|
||||||
|
%0 = ptr.load %self.p-example-property-5 : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
; p1 = Person new(name:'John Doe', age:34).
|
||||||
|
%Person = ivy.global-ref @Person : ptr
|
||||||
|
%0 = ivy.str.constant "John Doe"
|
||||||
|
%1 = i32.constant 34
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %Person, new(name:%0, age:%1) -> #ivy.id
|
||||||
|
|
||||||
|
%p1 = ptr.alloca #ivy.id -> ptr
|
||||||
|
ptr.store %2, %p1 : #ivy.id, ptr
|
||||||
|
|
||||||
|
; p1 set-age:100 in-unit:$months.
|
||||||
|
%3 = ptr.load %p1 : ptr -> #ivy.id
|
||||||
|
%4 = i32.constant 100
|
||||||
|
%5 = ivy.atom "months"
|
||||||
|
ivy.msg.send to %3, set-age:%4 in-units:%5 -> void
|
||||||
|
|
||||||
|
; p1 test(param:'Hello', 'World').
|
||||||
|
%6 = ptr.load %p1 : ptr -> #ivy.id
|
||||||
|
%7 = ivy.str.constant "Hello"
|
||||||
|
%8 = ivy.str.constant "World"
|
||||||
|
ivy.msg.send to %6, test(param:%7, _:%8) -> void
|
||||||
|
|
||||||
|
; i = 0.
|
||||||
|
%i = ptr.alloca i32 -> ptr
|
||||||
|
%9 = i32.constant 0
|
||||||
|
ptr.store %9, %i : i32, ptr
|
||||||
|
|
||||||
|
; while i < 100 do
|
||||||
|
^while.cond:
|
||||||
|
; i < 100
|
||||||
|
%10 = ptr.load %i : ptr -> i32
|
||||||
|
%11 = i32.constant 100
|
||||||
|
%cmptmp = ivy.cmp lt %10, %11 : (i32, i32) -> i1
|
||||||
|
scf.condition(%cmptmp)
|
||||||
|
cf.br-cond %cmptmp, ^while.body, ^while.end
|
||||||
|
|
||||||
|
^while.body:
|
||||||
|
; cout put:'Count is {i}'.
|
||||||
|
%12 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
%13 = ivy.str.constant "Count is "
|
||||||
|
ivy.msg.send to %12, append:%13 -> void
|
||||||
|
|
||||||
|
%14 = ptr.load %i : ptr -> i32
|
||||||
|
ivy.msg.send to %12, append:14 -> void
|
||||||
|
|
||||||
|
%15 = ivy.msg.send to %12, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%16 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %16, put:%15 -> void
|
||||||
|
|
||||||
|
; i += 2
|
||||||
|
%17 = ptr.load %i : ptr -> i32
|
||||||
|
%18 = i32.constant 2
|
||||||
|
%addtmp = ivy.add %17, %18 : (i32, i32) -> i32
|
||||||
|
ptr.store %addtmp, %i : i32, ptr
|
||||||
|
cf.br ^while.cond
|
||||||
|
|
||||||
|
^while.end:
|
||||||
|
; 0 to:100 step:2
|
||||||
|
%19 = i32.constant 0
|
||||||
|
%20 = i32.constant 100
|
||||||
|
%21 = i32.constant 2
|
||||||
|
%22 = ivy.msg.send to %19, to:%20 step:%21 -> #ivy.id
|
||||||
|
|
||||||
|
%for.iv.0 = ivy.msg.send to %22, value -> #ivy.id
|
||||||
|
cf.br ^for.cond(%for.iv.0: #ivy.id)
|
||||||
|
|
||||||
|
^for.step:
|
||||||
|
ivy.msg.send to %22, move-next -> void
|
||||||
|
%for.iv.next = ivy.msg.send to %22, value -> #ivy.id
|
||||||
|
cf.br ^for.cond(%for.iv.next: #ivy.id)
|
||||||
|
|
||||||
|
^for.cond(%iv: #ivy.id):
|
||||||
|
%for.valid = ivy.is-null-ref %iv : #ivy.id -> i1
|
||||||
|
cf.br-cond %for.valid, ^for.body(%iv: #ivy.id), ^for.end
|
||||||
|
|
||||||
|
^for.body(%x: #ivy.id):
|
||||||
|
; for x in 0 to:100 step:2 do
|
||||||
|
%23 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
; 'Count is {x}'
|
||||||
|
%24 = ivy.str.constant "Count is "
|
||||||
|
ivy.msg.send to %23, append:%24 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %23, append:%x -> void
|
||||||
|
|
||||||
|
%25 = ivy.msg.send to %23, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:"Count is {x}"
|
||||||
|
%26 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %26, put:%25 -> void
|
||||||
|
|
||||||
|
cf.br ^for.step
|
||||||
|
|
||||||
|
^for.end:
|
||||||
|
; 0 to:100 step:2 do:...
|
||||||
|
%27 = i32.constant 0
|
||||||
|
%28 = i32.constant 100
|
||||||
|
%29 = i32.constant 2
|
||||||
|
; [ :i | cout put:'Count: {i}' ]
|
||||||
|
%30 = ivy.lambda.create %lambda.0 -> #ivy.id
|
||||||
|
|
||||||
|
; 0 to:100 step:2 do:[ :i | cout put:'Count: {i}' ].
|
||||||
|
ivy.msg.send to %27, to:%28 step:%29 do:%30
|
||||||
|
|
||||||
|
; q = 32.
|
||||||
|
%q = ptr.alloca i32 -> ptr
|
||||||
|
%31 = i32.constant 32
|
||||||
|
ptr.store %31, %q : i32, ptr
|
||||||
|
|
||||||
|
; l = [ cout put:'Value of q is {q}' ].
|
||||||
|
%l = ptr.alloca #ivy.id
|
||||||
|
%32 = ptr.load %q : ptr -> i32
|
||||||
|
%lambda.env = ivy.pkg.create -> #ivy.id
|
||||||
|
ivy.pkg.put %lambda.env[@q] = %32 : (#ivy.id, #ivy.id)
|
||||||
|
|
||||||
|
%33 = ivy.lambda.create <%lambda.env> %lambda.1 -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %33, %l : #ivy.id, ptr
|
||||||
|
|
||||||
|
; q = 64.
|
||||||
|
%34 = i32.constant 64
|
||||||
|
ptr.store %34, %q : i32, ptr
|
||||||
|
|
||||||
|
; l call.
|
||||||
|
%35 = ptr.load %l : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %35, call -> void
|
||||||
|
|
||||||
|
%j = ptr.alloca i32 -> ptr
|
||||||
|
|
||||||
|
%36 = i32.constant 32
|
||||||
|
ptr.store %36, %j : i32, ptr
|
||||||
|
|
||||||
|
%37 = ptr.load %i : ptr -> i32
|
||||||
|
%38 = ptr.load %j : ptr -> i32
|
||||||
|
|
||||||
|
%cmptmp = arith.cmp lt %37, %38 : (i32, i32) -> i1
|
||||||
|
|
||||||
|
%39 = ivy.lambda : () -> void {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%0 = ivy.str.constant "True!"
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %1, put:%0 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%40 = ivy.lambda : () -> void {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%0 = ivy.str.constant "False!"
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %1, put:%0 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.msg.send to %cmptmp, if:%39 else:%40 -> void
|
||||||
|
|
||||||
|
%41 = ptr.load %i : ptr -> i32
|
||||||
|
%42 = ptr.load %j : ptr -> i32
|
||||||
|
|
||||||
|
%cmptmp.0 = arith.cmp lt %41, %42 : (i32, i32) -> i1
|
||||||
|
|
||||||
|
scf.if %cmptmp.0 -> void {
|
||||||
|
%43 = ivy.str.constant "True!"
|
||||||
|
%44 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %44, put:%43 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; pkg = {}.
|
||||||
|
%pkg = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
|
||||||
|
%45 = ivy.pkg.create -> #ivy.id
|
||||||
|
ptr.store %45, %pkg : #ivy.id, ptr
|
||||||
|
|
||||||
|
; pkg[0] = 16.
|
||||||
|
%46 = ptr.load %pkg : ptr -> #ivy.id
|
||||||
|
%47 = i32.constant 0
|
||||||
|
%48 = i32.constant 16
|
||||||
|
|
||||||
|
ivy.msg.send to %46, at:%47 put:%48 -> void
|
||||||
|
|
||||||
|
; tuple = (32, 'a string')
|
||||||
|
%tuple = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%49 = i32.constant 32
|
||||||
|
%50 = ivy.str.constant "a string"
|
||||||
|
|
||||||
|
%51 = ivy.tuple.create %49, %50 : (i32, #ivy.id) -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %51, %tuple : #ivy.id, ptr
|
||||||
|
|
||||||
|
%52 = ptr.load %tuple : ptr -> #ivy.id
|
||||||
|
%53 = ivy.msg.send to %52, get-iterator -> #ivy.id
|
||||||
|
|
||||||
|
ivy.for %54 in %53 -> void {
|
||||||
|
%key = ivy.tuple.get-item %54[0] : #ivy.id -> #ivy.id
|
||||||
|
%val = ivy.tuple.get-item %54[1] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
; '{key} -> {val}'
|
||||||
|
%55 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %55, append:%key -> void
|
||||||
|
|
||||||
|
%56 = ivy.str.constant " -> "
|
||||||
|
ivy.msg.send to %55, append:%56 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %55, append:%val -> void
|
||||||
|
|
||||||
|
%57 = ivy.msg.send to %23, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%58 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %58, put:%57 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; _ = 3 * 2.
|
||||||
|
%59 = i32.constant 3
|
||||||
|
%60 = i32.constant 2
|
||||||
|
%multmp = arith.mul %59, %60 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
; a = (32, 64).
|
||||||
|
%a = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%61 = i32.constant 32
|
||||||
|
%62 = i32.constant 64
|
||||||
|
%63 = ivy.tuple.create %61, %62 : (i32, i32) -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %63, %a : #ivy.id, ptr
|
||||||
|
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%64 = ptr.load %a : ptr -> #ivy.id
|
||||||
|
%65 = ivy.tuple.get-item %64[1] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %65, %v : #ivy.id, ptr
|
||||||
|
|
||||||
|
%66 = ivy.atom "err:number-format"
|
||||||
|
|
||||||
|
ivy.try -> void {
|
||||||
|
|
||||||
|
} catch (%ex = %66), %data {
|
||||||
|
|
||||||
|
} catch-all %ex, %data {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
%67 = ivy.lambda : () -> void {
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
%Int = ivy.global-ref @Int -> ptr
|
||||||
|
%0 = ivy.str.constant "342"
|
||||||
|
|
||||||
|
%1 = ivy.msg.send to %Int, parse:%0
|
||||||
|
|
||||||
|
ptr.store %1, %v : #ivy.id, ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
%68 = ivy.lambda %err, %data : (#ivy.id, #ivy.id) -> void {
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%key -> void
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Cannot parse integer string ("
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%err -> void
|
||||||
|
|
||||||
|
%2 = ivy.str.constant ")"
|
||||||
|
ivy.msg.send to %0, append:%2 -> void
|
||||||
|
|
||||||
|
%3 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%4 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %4, put:%3 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%69 = ivy.lambda %err, %data : (#ivy.id, #ivy.id) -> void {
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%key -> void
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Error "
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%err -> void
|
||||||
|
|
||||||
|
%2 = ivy.str.constant " occurred ("
|
||||||
|
ivy.msg.send to %0, append:%2 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%data -> void
|
||||||
|
|
||||||
|
%3 = ivy.str.constant ")"
|
||||||
|
|
||||||
|
%4 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%5 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %5, put:%4 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%70 = ivy.atom "err:number-format"
|
||||||
|
ivy.msg.send to %67, on:%70 do:%68 -> #ivy.id
|
||||||
|
ivy.msg.send to %67, on-error:%69 -> void
|
||||||
|
ivy.msg.send to %67, call -> void
|
||||||
|
}
|
||||||
|
}
|
||||||
535
doc/mie/sample/Person.3.mie
Normal file
535
doc/mie/sample/Person.3.mie
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
meta.source-filename "Person.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder : ptr
|
||||||
|
|
||||||
|
ivy.class @Person {
|
||||||
|
%self.name = ivy.object-var @name : #ivy.id -> ptr
|
||||||
|
%self.age = ivy.object-var @age : #ivy.id -> ptr
|
||||||
|
%self.val = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
%self.__example-property-4 = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
%self.__example-property-5 = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
|
||||||
|
%lambda.0 = ivy.lambda.body <%env> (%i: #ivy.id) -> void {
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder -> ptr
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Count is "
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%i -> void
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %3, put:%2 -> void
|
||||||
|
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
%lambda.1 = ivy.lambda.body <%env> () -> void {
|
||||||
|
%env.q = ivy.pkg.get %env[@q] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder -> ptr
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Value of q is "
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%env.q -> void
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %3, put:%2 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func init(name:%name, age:%age) -> void {
|
||||||
|
ptr.store %name, %self.name : #ivy.id, ptr
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func test(param:%data, _:%extra) -> void {
|
||||||
|
%0 = ptr.load %StringBuilder : ptr -> #ivy.id
|
||||||
|
%1 = ivy.msg.send to %0, new -> #ivy.id
|
||||||
|
|
||||||
|
%2 = ivy.str.constant "Received "
|
||||||
|
ivy.msg.send to %1, append:%2 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %1, append:%data -> void
|
||||||
|
|
||||||
|
%3 = ivy.str.constant ", "
|
||||||
|
ivy.msg.send to %1, append:%3 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %1, append:%extra -> void
|
||||||
|
|
||||||
|
%4 = ivy.msg.send to %1, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%5 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %5, put:%4 -> void
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func name -> #ivy.id {
|
||||||
|
%0 = ptr.load %self.name : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func age -> #ivy.id {
|
||||||
|
%0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func age-in-months -> #ivy.id {
|
||||||
|
%0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%1 = i32.constant 12
|
||||||
|
%multmp = ivy.mul %0, %1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
func.return %multmp : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func set-name:%name -> void {
|
||||||
|
ptr.store %name, %self.name : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func set-age:%age -> void {
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func set-age:%age in-units:%units -> void {
|
||||||
|
^switch.cond.0:
|
||||||
|
%0 = ivy.atom "years"
|
||||||
|
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.0, ^switch.body.0, ^switch.cond.1
|
||||||
|
|
||||||
|
^switch.body.0:
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.cond.1:
|
||||||
|
%1 = ivy.atom "months"
|
||||||
|
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.1, ^switch.body.1, ^switch.cond.2
|
||||||
|
|
||||||
|
^switch.body.1:
|
||||||
|
%d0 = i32.constant 12
|
||||||
|
%divtmp.0 = ivy.div %age, %d0 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
ptr.store %divtmp.0, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.cond.2:
|
||||||
|
%2 = ivy.atom "days"
|
||||||
|
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.2, ^switch.body.2, ^switch.default
|
||||||
|
|
||||||
|
^switch.body.2:
|
||||||
|
%d1 = i32.constant 365
|
||||||
|
%divtmp.1 = ivy.div %age, %d1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
ptr.store %divtmp.1, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.default:
|
||||||
|
%d2 = i32.constant 0
|
||||||
|
ptr.store %d2, %self.age : #ivy.id, ptr
|
||||||
|
cf.br ^switch.end.0
|
||||||
|
|
||||||
|
^switch.end:
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.func get-age-in-units:%units -> #ivy.id {
|
||||||
|
^switch.cond.0:
|
||||||
|
%0 = ivy.atom "years"
|
||||||
|
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.0, ^switch.body.0, ^switch.cond.1
|
||||||
|
|
||||||
|
^switch.body.0:
|
||||||
|
%v0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
cf.br ^switch.end(%v0: #ivy.id)
|
||||||
|
|
||||||
|
^switch.cond.1:
|
||||||
|
%1 = ivy.atom "months"
|
||||||
|
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.1, ^switch.body.1, ^switch.cond.2
|
||||||
|
|
||||||
|
^switch.body.1:
|
||||||
|
%v0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%d0 = i32.constant 12
|
||||||
|
%divtmp.0 = ivy.div %v0, %d0 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
cf.br ^switch.end(%divtmp.0: #ivy.id)
|
||||||
|
|
||||||
|
^switch.cond.2:
|
||||||
|
%2 = ivy.atom "days"
|
||||||
|
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
cf.br-cond %cmptmp.2, ^switch.body.2, ^switch.default
|
||||||
|
|
||||||
|
^switch.body.2:
|
||||||
|
%v1 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%d1 = i32.constant 365
|
||||||
|
%divtmp.1 = ivy.div %v1, %d1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
cf.br ^switch.end(%divtmp.1: #ivy.id)
|
||||||
|
|
||||||
|
^switch.default:
|
||||||
|
%d2 = i32.constant 0
|
||||||
|
cf.br ^switch.end(%d2.1: i32)
|
||||||
|
|
||||||
|
^switch.end(%result: #ivy.id):
|
||||||
|
func.return %result : #ivy.id
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.prop example-property
|
||||||
|
get {
|
||||||
|
%0 = ptr.load %self.val : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
set (%value: #ivy.id) {
|
||||||
|
ptr.store %value, %self.val : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.prop example-property-2 get {
|
||||||
|
%0 = ptr.load %self.val : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
} set (%x: #ivy.id) {
|
||||||
|
ptr.store %x, %self.val : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.prop example-property-3 get {
|
||||||
|
%0 = i32.constant 42
|
||||||
|
func.return %0 : i32
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.prop example-property-4 get {
|
||||||
|
%0 = ptr.load %self.p-example-property-4 : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
} set (%0: #ivy.id) {
|
||||||
|
ptr.store %0, %self.p-example-property-4 : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object.prop example-property-5 get {
|
||||||
|
%0 = ptr.load %self.p-example-property-5 : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
; p1 = Person new(name:'John Doe', age:34).
|
||||||
|
%Person = ivy.global-ref @Person : ptr
|
||||||
|
%0 = ivy.str.constant "John Doe"
|
||||||
|
%1 = i32.constant 34
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %Person, new(name:%0, age:%1) -> #ivy.id
|
||||||
|
|
||||||
|
%p1 = ptr.alloca #ivy.id -> ptr
|
||||||
|
ptr.store %2, %p1 : #ivy.id, ptr
|
||||||
|
|
||||||
|
; p1 set-age:100 in-unit:$months.
|
||||||
|
%3 = ptr.load %p1 : ptr -> #ivy.id
|
||||||
|
%4 = i32.constant 100
|
||||||
|
%5 = ivy.atom "months"
|
||||||
|
ivy.msg.send to %3, set-age:%4 in-units:%5 -> void
|
||||||
|
|
||||||
|
; p1 test(param:'Hello', 'World').
|
||||||
|
%6 = ptr.load %p1 : ptr -> #ivy.id
|
||||||
|
%7 = ivy.str.constant "Hello"
|
||||||
|
%8 = ivy.str.constant "World"
|
||||||
|
ivy.msg.send to %6, test(param:%7, _:%8) -> void
|
||||||
|
|
||||||
|
; i = 0.
|
||||||
|
%i = ptr.alloca i32 -> ptr
|
||||||
|
%9 = i32.constant 0
|
||||||
|
ptr.store %9, %i : i32, ptr
|
||||||
|
cf.br ^while.cond
|
||||||
|
|
||||||
|
; while i < 100 do
|
||||||
|
^while.cond:
|
||||||
|
; i < 100
|
||||||
|
%10 = ptr.load %i : ptr -> i32
|
||||||
|
%11 = i32.constant 100
|
||||||
|
%cmptmp = ivy.cmp lt %10, %11 : (i32, i32) -> i1
|
||||||
|
scf.condition(%cmptmp)
|
||||||
|
cf.br-cond %cmptmp, ^while.body, ^while.end
|
||||||
|
|
||||||
|
^while.body:
|
||||||
|
; cout put:'Count is {i}'.
|
||||||
|
%12 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
%13 = ivy.str.constant "Count is "
|
||||||
|
ivy.msg.send to %12, append:%13 -> void
|
||||||
|
|
||||||
|
%14 = ptr.load %i : ptr -> i32
|
||||||
|
ivy.msg.send to %12, append:14 -> void
|
||||||
|
|
||||||
|
%15 = ivy.msg.send to %12, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%16 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %16, put:%15 -> void
|
||||||
|
|
||||||
|
; i += 2
|
||||||
|
%17 = ptr.load %i : ptr -> i32
|
||||||
|
%18 = i32.constant 2
|
||||||
|
%addtmp = ivy.add %17, %18 : (i32, i32) -> i32
|
||||||
|
ptr.store %addtmp, %i : i32, ptr
|
||||||
|
cf.br ^while.cond
|
||||||
|
|
||||||
|
^while.end:
|
||||||
|
; 0 to:100 step:2
|
||||||
|
%19 = i32.constant 0
|
||||||
|
%20 = i32.constant 100
|
||||||
|
%21 = i32.constant 2
|
||||||
|
%22 = ivy.msg.send to %19, to:%20 step:%21 -> #ivy.id
|
||||||
|
|
||||||
|
cf.br ^for.init(%22: #ivy.id)
|
||||||
|
|
||||||
|
^for.init(%it: #ivy.id):
|
||||||
|
%for.iv.0 = ivy.msg.send to %it, value -> #ivy.id
|
||||||
|
cf.br ^for.cond(%it: #ivy.id, %for.iv.0: #ivy.id)
|
||||||
|
|
||||||
|
^for.step(%it: #ivy.id):
|
||||||
|
ivy.msg.send to %22, move-next -> void
|
||||||
|
%for.iv.next = ivy.msg.send to %22, value -> #ivy.id
|
||||||
|
cf.br ^for.cond(%it: #ivy.id, %for.iv.next: #ivy.id)
|
||||||
|
|
||||||
|
^for.cond(%it: #ivy.id, %iv: #ivy.id):
|
||||||
|
%for.valid = ivy.is-null-ref %iv : #ivy.id -> i1
|
||||||
|
cf.br-cond %for.valid, ^for.body(%it: #ivy.id, %iv: #ivy.id), ^for.end
|
||||||
|
|
||||||
|
^for.body(%it: #ivy.id, %x: #ivy.id):
|
||||||
|
; for x in 0 to:100 step:2 do
|
||||||
|
%23 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
; 'Count is {x}'
|
||||||
|
%24 = ivy.str.constant "Count is "
|
||||||
|
ivy.msg.send to %23, append:%24 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %23, append:%x -> void
|
||||||
|
|
||||||
|
%25 = ivy.msg.send to %23, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:"Count is {x}"
|
||||||
|
%26 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %26, put:%25 -> void
|
||||||
|
|
||||||
|
cf.br ^for.step(%it: #ivy.id)
|
||||||
|
|
||||||
|
^for.end:
|
||||||
|
; 0 to:100 step:2 do:...
|
||||||
|
%27 = i32.constant 0
|
||||||
|
%28 = i32.constant 100
|
||||||
|
%29 = i32.constant 2
|
||||||
|
; [ :i | cout put:'Count: {i}' ]
|
||||||
|
%30 = ivy.lambda.create %lambda.0 -> #ivy.id
|
||||||
|
|
||||||
|
; 0 to:100 step:2 do:[ :i | cout put:'Count: {i}' ].
|
||||||
|
ivy.msg.send to %27, to:%28 step:%29 do:%30
|
||||||
|
|
||||||
|
; q = 32.
|
||||||
|
%q = ptr.alloca i32 -> ptr
|
||||||
|
%31 = i32.constant 32
|
||||||
|
ptr.store %31, %q : i32, ptr
|
||||||
|
|
||||||
|
; l = [ cout put:'Value of q is {q}' ].
|
||||||
|
%l = ptr.alloca #ivy.id
|
||||||
|
%32 = ptr.load %q : ptr -> i32
|
||||||
|
%lambda.env = ivy.pkg.create -> #ivy.id
|
||||||
|
ivy.pkg.put %lambda.env[@q] = %32 : (#ivy.id, #ivy.id)
|
||||||
|
|
||||||
|
%33 = ivy.lambda.create <%lambda.env> %lambda.1 -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %33, %l : #ivy.id, ptr
|
||||||
|
|
||||||
|
; q = 64.
|
||||||
|
%34 = i32.constant 64
|
||||||
|
ptr.store %34, %q : i32, ptr
|
||||||
|
|
||||||
|
; l call.
|
||||||
|
%35 = ptr.load %l : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %35, call -> void
|
||||||
|
|
||||||
|
%j = ptr.alloca i32 -> ptr
|
||||||
|
|
||||||
|
%36 = i32.constant 32
|
||||||
|
ptr.store %36, %j : i32, ptr
|
||||||
|
|
||||||
|
%37 = ptr.load %i : ptr -> i32
|
||||||
|
%38 = ptr.load %j : ptr -> i32
|
||||||
|
|
||||||
|
%cmptmp = arith.cmp lt %37, %38 : (i32, i32) -> i1
|
||||||
|
|
||||||
|
%39 = ivy.lambda : () -> void {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%0 = ivy.str.constant "True!"
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %1, put:%0 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%40 = ivy.lambda : () -> void {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%0 = ivy.str.constant "False!"
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %1, put:%0 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.msg.send to %cmptmp, if:%39 else:%40 -> void
|
||||||
|
|
||||||
|
%41 = ptr.load %i : ptr -> i32
|
||||||
|
%42 = ptr.load %j : ptr -> i32
|
||||||
|
|
||||||
|
%cmptmp.0 = arith.cmp lt %41, %42 : (i32, i32) -> i1
|
||||||
|
|
||||||
|
scf.if %cmptmp.0 -> void {
|
||||||
|
%43 = ivy.str.constant "True!"
|
||||||
|
%44 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %44, put:%43 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; pkg = {}.
|
||||||
|
%pkg = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
|
||||||
|
%45 = ivy.pkg.create -> #ivy.id
|
||||||
|
ptr.store %45, %pkg : #ivy.id, ptr
|
||||||
|
|
||||||
|
; pkg[0] = 16.
|
||||||
|
%46 = ptr.load %pkg : ptr -> #ivy.id
|
||||||
|
%47 = i32.constant 0
|
||||||
|
%48 = i32.constant 16
|
||||||
|
|
||||||
|
ivy.msg.send to %46, at:%47 put:%48 -> void
|
||||||
|
|
||||||
|
; tuple = (32, 'a string')
|
||||||
|
%tuple = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%49 = i32.constant 32
|
||||||
|
%50 = ivy.str.constant "a string"
|
||||||
|
|
||||||
|
%51 = ivy.tuple.create %49, %50 : (i32, #ivy.id) -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %51, %tuple : #ivy.id, ptr
|
||||||
|
|
||||||
|
%52 = ptr.load %tuple : ptr -> #ivy.id
|
||||||
|
%53 = ivy.msg.send to %52, get-iterator -> #ivy.id
|
||||||
|
|
||||||
|
ivy.for %54 in %53 -> void {
|
||||||
|
%key = ivy.tuple.get-item %54[0] : #ivy.id -> #ivy.id
|
||||||
|
%val = ivy.tuple.get-item %54[1] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
; '{key} -> {val}'
|
||||||
|
%55 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %55, append:%key -> void
|
||||||
|
|
||||||
|
%56 = ivy.str.constant " -> "
|
||||||
|
ivy.msg.send to %55, append:%56 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %55, append:%val -> void
|
||||||
|
|
||||||
|
%57 = ivy.msg.send to %23, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%58 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %58, put:%57 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; _ = 3 * 2.
|
||||||
|
%59 = i32.constant 3
|
||||||
|
%60 = i32.constant 2
|
||||||
|
%multmp = arith.mul %59, %60 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
; a = (32, 64).
|
||||||
|
%a = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%61 = i32.constant 32
|
||||||
|
%62 = i32.constant 64
|
||||||
|
%63 = ivy.tuple.create %61, %62 : (i32, i32) -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %63, %a : #ivy.id, ptr
|
||||||
|
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%64 = ptr.load %a : ptr -> #ivy.id
|
||||||
|
%65 = ivy.tuple.get-item %64[1] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %65, %v : #ivy.id, ptr
|
||||||
|
|
||||||
|
%66 = ivy.atom "err:number-format"
|
||||||
|
|
||||||
|
ivy.try -> void {
|
||||||
|
|
||||||
|
} catch (%ex = %66), %data {
|
||||||
|
|
||||||
|
} catch-all %ex, %data {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
%67 = ivy.lambda : () -> void {
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
%Int = ivy.global-ref @Int -> ptr
|
||||||
|
%0 = ivy.str.constant "342"
|
||||||
|
|
||||||
|
%1 = ivy.msg.send to %Int, parse:%0
|
||||||
|
|
||||||
|
ptr.store %1, %v : #ivy.id, ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
%68 = ivy.lambda %err, %data : (#ivy.id, #ivy.id) -> void {
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%key -> void
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Cannot parse integer string ("
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%err -> void
|
||||||
|
|
||||||
|
%2 = ivy.str.constant ")"
|
||||||
|
ivy.msg.send to %0, append:%2 -> void
|
||||||
|
|
||||||
|
%3 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%4 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %4, put:%3 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%69 = ivy.lambda %err, %data : (#ivy.id, #ivy.id) -> void {
|
||||||
|
%0 = ivy.msg.send to %StringBuilder, new -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%key -> void
|
||||||
|
|
||||||
|
%1 = ivy.str.constant "Error "
|
||||||
|
ivy.msg.send to %0, append:%1 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%err -> void
|
||||||
|
|
||||||
|
%2 = ivy.str.constant " occurred ("
|
||||||
|
ivy.msg.send to %0, append:%2 -> void
|
||||||
|
|
||||||
|
ivy.msg.send to %0, append:%data -> void
|
||||||
|
|
||||||
|
%3 = ivy.str.constant ")"
|
||||||
|
|
||||||
|
%4 = ivy.msg.send to %0, to-string -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%5 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %5, put:%4 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%70 = ivy.atom "err:number-format"
|
||||||
|
ivy.msg.send to %67, on:%70 do:%68 -> #ivy.id
|
||||||
|
ivy.msg.send to %67, on-error:%69 -> void
|
||||||
|
ivy.msg.send to %67, call -> void
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,146 +1,460 @@
|
|||||||
record package_scope = str "net.doorstuck.test"
|
meta.source-filename "Person.im"
|
||||||
|
|
||||||
record import = { str "std.io" }
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
data @cout = external global id
|
ivy.package-ref "std.io"
|
||||||
data @StringBuffer = external global id
|
|
||||||
|
|
||||||
data @.str.0 = str "Received "
|
ivy.module {
|
||||||
data @.str.1 = str ", "
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
|
||||||
data @.atom.0 = atom "years"
|
ivy.class @Person {
|
||||||
data @.atom.1 = atom "months"
|
%self.name = ivy.object-var @name : #ivy.id -> ptr
|
||||||
data @.atom.2 = atom "days"
|
%self.age = ivy.object-var @age : #ivy.id -> ptr
|
||||||
|
%self.val = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
%self.__example-property-4 = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
%self.__example-property-5 = ivy.object-var @val : #ivy.id -> ptr
|
||||||
|
|
||||||
type @_ZN3net9doorstuck4testC6PersonE = class {
|
ivy.msgh.object init(name:%name, age:%age) -> void {
|
||||||
id @name,
|
ptr.store %name, %self.name : #ivy.id, ptr
|
||||||
id @age,
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
id @val
|
func.return : ()
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @_ZN3net9doorstuck4testC6PersonM4init4name3ageE(id %self, id %0) instance {
|
ivy.msgh.object test(param:%data, _:%extra) -> void {
|
||||||
entry:
|
%0 = ivy.string-builder.begin
|
||||||
%1 = getelementptr class @_ZN3net9doorstuck4testC6PersonE, id %self, i32 #0
|
|
||||||
store id %0, ptr %1
|
ivy.string-builder.add %0 << "Received "
|
||||||
|
ivy.string-builder.add %0 << %data : #ivy.id
|
||||||
%2 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
ivy.string-builder.add %0 << ", "
|
||||||
store id %1, ptr %2
|
ivy.string-builder.add %0 << %extra : #ivy.id
|
||||||
|
|
||||||
ret void
|
%1 = ivy.string-builder.end %0 -> #ivy.id
|
||||||
}
|
|
||||||
|
%2 = ptr.load %cout : ptr -> #ivy.id
|
||||||
define void @_ZN3net9doorstuck4testC6PersonM4test5param0E(id %0, id %1) instance {
|
ivy.msg.send to %2, put:%1 -> void
|
||||||
entry:
|
func.return : ()
|
||||||
%2 = load id, ptr @cout
|
}
|
||||||
|
|
||||||
; %4 = StringBuilder new
|
ivy.msgh.object name -> #ivy.id {
|
||||||
%3 = load id, ptr @StringBuilder
|
%0 = ptr.load %self.name : ptr -> #ivy.id
|
||||||
%4 = msg id %3, @_M3newE
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
; (void) tempstr append:'Received '
|
|
||||||
%5 = load id, ptr @.str.0
|
ivy.msgh.object age -> #ivy.id {
|
||||||
msg void, id %3, @_M06appendE [id %5]
|
%0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
; (void) tempstr append:data (param 0)
|
}
|
||||||
msg void, id %3, @_M06appendE [id %0]
|
|
||||||
|
ivy.msgh.object age-in-months -> #ivy.id {
|
||||||
; (void) tempstr append:', '
|
%0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
%6 = load id, ptr @.str.1
|
%1 = i32.constant 12
|
||||||
msg void, id %3, @_M06appendE [id %6]
|
%multmp = ivy.mul %0, %1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
func.return %multmp : #ivy.id
|
||||||
; [void] tempstr append:extra (param 1)
|
}
|
||||||
msg void, id %3, @_M06appendE [id %1]
|
|
||||||
|
ivy.msgh.object set-name:%name -> void {
|
||||||
; %7 = tempstr toString
|
ptr.store %name, %self.name : #ivy.id, ptr
|
||||||
%7 = msg id, id %3, @_M8toStringE
|
func.return : ()
|
||||||
|
}
|
||||||
; cout put:'Received {data}, {extra}'
|
|
||||||
msg void, id %2, @_M03put [id %7]
|
ivy.msgh.object set-age:%age -> void {
|
||||||
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
ret void
|
func.return : ()
|
||||||
}
|
}
|
||||||
|
|
||||||
define id @_ZN3net9doorstuck4testC6PersonM4nameE(id %self) instance {
|
ivy.msgh.object set-age:%age in-units:%units -> void {
|
||||||
entry:
|
scf.switch : () -> void
|
||||||
%0 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #0
|
case {
|
||||||
%1 = load id, ptr %0
|
%0 = ivy.atom "years"
|
||||||
ret id %1
|
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
|
||||||
}
|
scf.switch-condition %cmptmp.0
|
||||||
|
} then {
|
||||||
define id @_ZN3net9doorstuck4testC6PersonM3ageE(id %self) instance {
|
ptr.store %age, %self.age : #ivy.id, ptr
|
||||||
entry:
|
scf.switch-break : ()
|
||||||
%0 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
} case {
|
||||||
%1 = load id, ptr %0
|
%1 = ivy.atom "months"
|
||||||
ret id %1
|
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
|
||||||
}
|
scf.condition %cmptmp.1
|
||||||
|
} then {
|
||||||
define id @_ZN3net9doorstuck4testC6PersonM11ageInMonthsE(id %self, id %0) instance {
|
%d0 = i32.constant 12
|
||||||
entry:
|
%divtmp.0 = ivy.div %age, %d0 : (#ivy.id, i32) -> #ivy.id
|
||||||
%1 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
ptr.store %divtmp.0, %self.age : #ivy.id, ptr
|
||||||
%2 = load id, ptr %1
|
scf.switch-break : ()
|
||||||
ret id %1
|
} case {
|
||||||
}
|
%2 = ivy.atom "days"
|
||||||
|
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
|
||||||
define void @_ZN3net9doorstuck4testC6PersonM07setNameE(id %self, id %1) instance {
|
scf.condition %cmptmp.2
|
||||||
entry:
|
} then {
|
||||||
%2 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
%d1 = i32.constant 365
|
||||||
store id %1, ptr %2
|
%divtmp.1 = ivy.div %age, %d1 : (#ivy.id, i32) -> #ivy.id
|
||||||
ret void
|
ptr.store %divtmp.1, %self.age : #ivy.id, ptr
|
||||||
}
|
scf.switch-break : ()
|
||||||
|
} default {
|
||||||
define void @_ZN3net9doorstuck4testC6PersonM06setAge6inUnitE(id %self, i32 %1, id %2) instance {
|
%d2 = i32.constant 0
|
||||||
entry:
|
scf.switch-break : ()
|
||||||
%3 = load atom, ptr @.atom.0
|
}
|
||||||
%4 = load atom, ptr @.atom.1
|
|
||||||
%5 = load atom, ptr @.atom.2
|
func.return : ()
|
||||||
|
}
|
||||||
switch id %2, label %default [
|
|
||||||
atom %3, label %years
|
ivy.msgh.object get-age-in-units:%units -> #ivy.id {
|
||||||
atom %4, label %months
|
%result = scf.switch : () -> #ivy.id
|
||||||
atom %5, label %days
|
case {
|
||||||
]
|
%0 = ivy.atom "years"
|
||||||
|
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
|
||||||
years:
|
scf.switch-condition %cmptmp.0
|
||||||
%6 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
} then {
|
||||||
store i32 %2, ptr %6
|
%v0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
br label %end
|
scf.switch-break %v0 : #ivy.id
|
||||||
|
} case {
|
||||||
months:
|
%1 = ivy.atom "months"
|
||||||
%7 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
|
||||||
%8 = div i32 %2, #12
|
scf.condition %cmptmp.1
|
||||||
store i32 %8, ptr %7
|
} then {
|
||||||
br label %end
|
%v0 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
|
%d0 = i32.constant 12
|
||||||
days:
|
%divtmp.0 = ivy.div %v0, %d0 : (#ivy.id, i32) -> #ivy.id
|
||||||
%9 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
scf.switch-break %divtmp.0 : #ivy.id
|
||||||
%10 = div i32 %2, #365
|
} case {
|
||||||
store i32 %10, ptr %9
|
%2 = ivy.atom "days"
|
||||||
br label %end
|
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
|
||||||
|
scf.condition %cmptmp.2
|
||||||
default:
|
} then {
|
||||||
%11 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
|
%v1 = ptr.load %self.age : ptr -> #ivy.id
|
||||||
store i32 #0, ptr %11
|
%d1 = i32.constant 365
|
||||||
br label %end
|
%divtmp.1 = ivy.div %v1, %d1 : (#ivy.id, i32) -> #ivy.id
|
||||||
|
scf.switch-break %divtmp.1 : #ivy.id
|
||||||
end:
|
} default {
|
||||||
ret void
|
%d2 = i32.constant 0
|
||||||
}
|
scf.switch-break %d2 : #ivy.id
|
||||||
|
}
|
||||||
define id @_ZN3net9doorstuck4testC6PersonM012getAgeInUnitE(id %0, id %1) instance {
|
|
||||||
entry:
|
func.return %result : #ivy.id
|
||||||
|
}
|
||||||
}
|
|
||||||
|
ivy.object-prop example-property
|
||||||
define id @_ZN3net9doorstuck4testC6PersonP15examplePropertyG(id %self) instance {
|
get {
|
||||||
entry:
|
%0 = ptr.load %self.val : ptr -> #ivy.id
|
||||||
%0 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #2
|
func.return %0 : #ivy.id
|
||||||
%1 = load id, ptr %0
|
}
|
||||||
ret id %1
|
set (%value: #ivy.id) {
|
||||||
}
|
ptr.store %value, %self.val : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
define void @_ZN3net9doorstuck4testC6PersonP15examplePropertyS(id %self, id %0) instance {
|
}
|
||||||
entry:
|
|
||||||
%1 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #2
|
ivy.object-prop example-property-2 get {
|
||||||
store id %0, ptr %1
|
%0 = ptr.load %self.val : ptr -> #ivy.id
|
||||||
ret void
|
func.return %0 : #ivy.id
|
||||||
|
} set (%x: #ivy.id) {
|
||||||
|
ptr.store %x, %self.val : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-3 get {
|
||||||
|
%0 = i32.constant 42
|
||||||
|
func.return %0 : i32
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-4 get {
|
||||||
|
%0 = ptr.load %self.__example-property-4 : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
} set (%0: #ivy.id) {
|
||||||
|
ptr.store %0, %self.__example-property-4 : #ivy.id, ptr
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.object-prop example-property-5 get {
|
||||||
|
%0 = ptr.load %self.__example-property-5 : ptr -> #ivy.id
|
||||||
|
func.return %0 : #ivy.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
; p1 = Person new(name:'John Doe', age:34).
|
||||||
|
%Person = ivy.global-ref @Person : ptr
|
||||||
|
%0 = ivy.str.constant "John Doe"
|
||||||
|
%1 = i32.constant 34
|
||||||
|
|
||||||
|
%2 = ivy.msg.send to %Person, new(name:%0, age:%1) -> #ivy.id
|
||||||
|
|
||||||
|
%p1 = ptr.alloca #ivy.id -> ptr
|
||||||
|
ptr.store %2, %p1 : #ivy.id, ptr
|
||||||
|
|
||||||
|
; p1 set-age:100 in-unit:$months.
|
||||||
|
%3 = ptr.load %p1 : ptr -> #ivy.id
|
||||||
|
%4 = i32.constant 100
|
||||||
|
%5 = ivy.atom "months"
|
||||||
|
ivy.msg.send to %3, set-age:%4 in-units:%5 -> void
|
||||||
|
|
||||||
|
; p1 test(param:'Hello', 'World').
|
||||||
|
%6 = ptr.load %p1 : ptr -> #ivy.id
|
||||||
|
%7 = ivy.str.constant "Hello"
|
||||||
|
%8 = ivy.str.constant "World"
|
||||||
|
ivy.msg.send to %6, test(param:%7, _:%8) -> void
|
||||||
|
|
||||||
|
; i = 0.
|
||||||
|
%i = ptr.alloca i32 -> ptr
|
||||||
|
%9 = i32.constant 0
|
||||||
|
ptr.store %9, %i : i32, ptr
|
||||||
|
|
||||||
|
; while i < 100 do
|
||||||
|
scf.while -> void {
|
||||||
|
; i < 100
|
||||||
|
%10 = ptr.load %i : ptr -> i32
|
||||||
|
%11 = i32.constant 100
|
||||||
|
%cmptmp = ivy.cmp lt %10, %11 : (i32, i32) -> i1
|
||||||
|
scf.condition(%cmptmp)
|
||||||
|
} do {
|
||||||
|
; cout put:'Count is {i}'.
|
||||||
|
%12 = ivy.string-builder.begin
|
||||||
|
|
||||||
|
ivy.string-builder.add %12 << "Count is "
|
||||||
|
|
||||||
|
%14 = ptr.load %i : ptr -> i32
|
||||||
|
ivy.string-builder.add %12 << %14 : i32
|
||||||
|
|
||||||
|
%15 = ivy.string-builder.end %12 -> #ivy.id
|
||||||
|
|
||||||
|
%16 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %16, put:%15 -> void
|
||||||
|
|
||||||
|
; i += 2
|
||||||
|
%17 = ptr.load %i : ptr -> i32
|
||||||
|
%18 = i32.constant 2
|
||||||
|
%addtmp = ivy.add %17, %18 : (i32, i32) -> i32
|
||||||
|
ptr.store %addtmp, %i : i32, ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
; 0 to:100 step:2
|
||||||
|
%19 = i32.constant 0
|
||||||
|
%20 = i32.constant 100
|
||||||
|
%21 = i32.constant 2
|
||||||
|
%22 = ivy.msg.send to %19, to:%20 step:%21 -> #ivy.id
|
||||||
|
|
||||||
|
; for x in 0 to:100 step:2 do
|
||||||
|
ivy.for %x in %22 -> void {
|
||||||
|
%23 = ivy.string-builder.begin
|
||||||
|
|
||||||
|
; 'Count is {x}'
|
||||||
|
ivy.string-builder.add %23 << "Count is "
|
||||||
|
ivy.string-builder.add %23 << %x : #ivy.id
|
||||||
|
|
||||||
|
%25 = ivy.string-builder.end %23 -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:"Count is {x}"
|
||||||
|
%26 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %26, put:%25 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; 0 to:100 step:2 do:...
|
||||||
|
%27 = i32.constant 0
|
||||||
|
%28 = i32.constant 100
|
||||||
|
%29 = i32.constant 2
|
||||||
|
; [ :i | cout put:'Count: {i}' ]
|
||||||
|
%30 = ivy.lambda %i : (#ivy.id) -> void {
|
||||||
|
%0 = ivy.string-builder.begin
|
||||||
|
|
||||||
|
ivy.string-builder.add %0 << "Count is "
|
||||||
|
ivy.string-builder.add %0 << %i : #ivy.id
|
||||||
|
|
||||||
|
%2 = ivy.string-builder.end %0 -> #ivy.id
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %3, put:%2 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; 0 to:100 step:2 do:[ :i | cout put:'Count: {i}' ].
|
||||||
|
ivy.msg.send to %27, to:%28 step:%29 do:%30
|
||||||
|
|
||||||
|
; q = 32.
|
||||||
|
%q = ptr.alloca i32 -> ptr
|
||||||
|
%31 = i32.constant 32
|
||||||
|
ptr.store %31, %q : i32, ptr
|
||||||
|
|
||||||
|
; l = [ cout put:'Value of q is {q}' ].
|
||||||
|
%l = ptr.alloca #ivy.id
|
||||||
|
%32 = ptr.load %q : ptr -> i32
|
||||||
|
%33 = ivy.lambda (%env.q = %32) : () -> void {
|
||||||
|
%0 = ivy.string-builder.begin
|
||||||
|
|
||||||
|
ivy.string-builder.add %0 << "Value of q is "
|
||||||
|
ivy.string-builder.add %0 << %env.q : #ivy.id
|
||||||
|
|
||||||
|
%2 = ivy.string-builder.end %0 -> #ivy.id
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %3, put:%2 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr.store %33, %l : #ivy.id, ptr
|
||||||
|
|
||||||
|
; q = 64.
|
||||||
|
%34 = i32.constant 64
|
||||||
|
ptr.store %34, %q : i32, ptr
|
||||||
|
|
||||||
|
; l call.
|
||||||
|
%35 = ptr.load %l : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %35, call -> void
|
||||||
|
|
||||||
|
%j = ptr.alloca i32 -> ptr
|
||||||
|
|
||||||
|
%36 = i32.constant 32
|
||||||
|
ptr.store %36, %j : i32, ptr
|
||||||
|
|
||||||
|
%37 = ptr.load %i : ptr -> i32
|
||||||
|
%38 = ptr.load %j : ptr -> i32
|
||||||
|
|
||||||
|
%cmptmp = arith.cmp lt %37, %38 : (i32, i32) -> i1
|
||||||
|
|
||||||
|
%39 = ivy.lambda : () -> void {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%0 = ivy.str.constant "True!"
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %1, put:%0 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%40 = ivy.lambda : () -> void {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%0 = ivy.str.constant "False!"
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %1, put:%0 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy.msg.send to %cmptmp, if:%39 else:%40 -> void
|
||||||
|
|
||||||
|
%41 = ptr.load %i : ptr -> i32
|
||||||
|
%42 = ptr.load %j : ptr -> i32
|
||||||
|
|
||||||
|
%cmptmp.0 = arith.cmp lt %41, %42 : (i32, i32) -> i1
|
||||||
|
|
||||||
|
scf.if %cmptmp.0 -> void {
|
||||||
|
%43 = ivy.str.constant "True!"
|
||||||
|
%44 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %44, put:%43 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; pkg = {}.
|
||||||
|
%pkg = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%Package = ivy.global-ref @std.lang.Package -> ptr
|
||||||
|
|
||||||
|
%45 = ivy.msg.send to %Package, new -> #ivy.id
|
||||||
|
ptr.store %45, %pkg : #ivy.id, ptr
|
||||||
|
|
||||||
|
; pkg[0] = 16.
|
||||||
|
%46 = ptr.load %pkg : ptr -> #ivy.id
|
||||||
|
%47 = i32.constant 0
|
||||||
|
%48 = i32.constant 16
|
||||||
|
|
||||||
|
ivy.msg.send to %46, at:%47 put:%48 -> void
|
||||||
|
|
||||||
|
; tuple = (32, 'a string')
|
||||||
|
%tuple = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%49 = i32.constant 32
|
||||||
|
%50 = ivy.str.constant "a string"
|
||||||
|
|
||||||
|
%51 = ivy.tuple.create %49, %50 : (i32, #ivy.id) -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %51, %tuple : #ivy.id, ptr
|
||||||
|
|
||||||
|
%52 = ptr.load %tuple : ptr -> #ivy.id
|
||||||
|
%53 = ivy.msg.send to %52, get-iterator -> #ivy.id
|
||||||
|
|
||||||
|
ivy.for %54 in %53 -> void {
|
||||||
|
%key = ivy.tuple.get-item %54[0] : (#ivy.id, i32) -> #ivy.id
|
||||||
|
%val = ivy.tuple.get-item %54[1] : (#ivy.id, i32) -> #ivy.id
|
||||||
|
|
||||||
|
; '{key} -> {val}'
|
||||||
|
%55 = ivy.string-builder.begin
|
||||||
|
|
||||||
|
ivy.string-builder.add %55 << %key : #ivy.id
|
||||||
|
ivy.string-builder.add %55 << " -> "
|
||||||
|
ivy.string-builder.add %55 << %val : #ivy.id
|
||||||
|
|
||||||
|
%57 = ivy.string-builder.end %55 -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%58 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %58, put:%57 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
; _ = 3 * 2.
|
||||||
|
%59 = i32.constant 3
|
||||||
|
%60 = i32.constant 2
|
||||||
|
%multmp = arith.mul %59, %60 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
; a = (32, 64).
|
||||||
|
%a = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%61 = i32.constant 32
|
||||||
|
%62 = i32.constant 64
|
||||||
|
%63 = ivy.tuple.create %61, %62 : (i32, i32) -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %63, %a : #ivy.id, ptr
|
||||||
|
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%64 = ptr.load %a : ptr -> #ivy.id
|
||||||
|
%65 = ivy.tuple.get-item %64[1] : #ivy.id -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %65, %v : #ivy.id, ptr
|
||||||
|
|
||||||
|
%66 = ivy.atom "err:number-format"
|
||||||
|
|
||||||
|
ivy.try -> void {
|
||||||
|
|
||||||
|
} catch (%ex = %66), %data {
|
||||||
|
|
||||||
|
} catch-all %ex, %data {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
%67 = ivy.lambda : () -> void {
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
%Int = ivy.global-ref @Int -> ptr
|
||||||
|
%0 = ivy.str.constant "342"
|
||||||
|
|
||||||
|
%1 = ivy.msg.send to %Int, parse:%0
|
||||||
|
|
||||||
|
ptr.store %1, %v : #ivy.id, ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
%68 = ivy.lambda %err, %data : (#ivy.id, #ivy.id) -> void {
|
||||||
|
%0 = ivy.string-builder.begin
|
||||||
|
|
||||||
|
ivy.string-builder.add %0 << "Cannot parse integer string ("
|
||||||
|
ivy.string-builder.add %0 << %err : #ivy.id
|
||||||
|
ivy.string-builder.add %0 << ")"
|
||||||
|
|
||||||
|
%3 = ivy.string-builder.end %0 -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%4 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %4, put:%3 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%69 = ivy.lambda %err, %data : (#ivy.id, #ivy.id) -> void {
|
||||||
|
%0 = ivy.string-builder.create
|
||||||
|
|
||||||
|
ivy.string-builder.add %0 << "Error "
|
||||||
|
ivy.string-builder.add %0 << %err : #ivy.id
|
||||||
|
ivy.string-builder.add %0 << " occurred ("
|
||||||
|
ivy.string-builder.add %0 << %data : #ivy.id
|
||||||
|
ivy.string-builder.add %0 << ")"
|
||||||
|
|
||||||
|
%4 = ivy.string-builder.end %0 -> #ivy.id
|
||||||
|
|
||||||
|
; cout put:'{key} -> {val}'
|
||||||
|
%5 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.msg.send to %5, put:%4 -> void
|
||||||
|
}
|
||||||
|
|
||||||
|
%70 = ivy.atom "err:number-format"
|
||||||
|
ivy.msg.send to %67, on:%70 do:%68 -> #ivy.id
|
||||||
|
ivy.msg.send to %67, on-error:%69 -> void
|
||||||
|
ivy.msg.send to %67, call -> void
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
doc/mie/sample/Simple.1.mie
Normal file
46
doc/mie/sample/Simple.1.mie
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
meta.source-filename "Simple.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
ivy.init-text {
|
||||||
|
%0 = i32.constant 32
|
||||||
|
%1 = i32.constant 64
|
||||||
|
%multmp = arith.mul %0, %1 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
%y = ptr.alloca i32
|
||||||
|
ptr.store %multmp, %y : i32, ptr
|
||||||
|
|
||||||
|
%2 = i32.constant 64
|
||||||
|
%3 = i32.constant 4
|
||||||
|
%divtmp = arith.div %2, %3 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
%z = ptr.alloca i32
|
||||||
|
ptr.store %divtmp, %z : i32, ptr
|
||||||
|
|
||||||
|
%4 = ptr.load %y : ptr -> i32
|
||||||
|
%5 = ptr.load %z : ptr -> i32
|
||||||
|
%addtmp = arith.add %4, %5 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
%x = ptr.alloca i32
|
||||||
|
ptr.store %addtmp, %x : i32, ptr
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
|
||||||
|
%6 = ivy.string-builder.begin
|
||||||
|
ivy.string-builder.add %6 << "Answer: "
|
||||||
|
|
||||||
|
%7 = ptr.load %x : ptr -> i32
|
||||||
|
ivy.string-builder.add %6 << %7 : i32
|
||||||
|
|
||||||
|
%8 = ivy.string-builder.end %6 -> #ivy.id
|
||||||
|
|
||||||
|
%9 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %9, put:%8 -> void
|
||||||
|
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
}
|
||||||
50
doc/mie/sample/Simple.2.mie
Normal file
50
doc/mie/sample/Simple.2.mie
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
meta.source-filename "Simple.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%StringBuilder = ivy.global-ref @std.lang.StringBuilder -> ptr
|
||||||
|
|
||||||
|
%.str.0 = ivy.str.constant "Answer: "
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
%0 = i32.constant 32
|
||||||
|
%1 = i32.constant 64
|
||||||
|
%multmp = arith.mul %0, %1 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
%y = ptr.alloca i32
|
||||||
|
ptr.store %multmp, %y : i32, ptr
|
||||||
|
|
||||||
|
%2 = i32.constant 64
|
||||||
|
%3 = i32.constant 4
|
||||||
|
%divtmp = arith.div %2, %3 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
%z = ptr.alloca i32
|
||||||
|
ptr.store %divtmp, %z : i32, ptr
|
||||||
|
|
||||||
|
%4 = ptr.load %y : ptr -> i32
|
||||||
|
%5 = ptr.load %z : ptr -> i32
|
||||||
|
%addtmp = arith.add %4, %5 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
%x = ptr.alloca i32
|
||||||
|
ptr.store %addtmp, %x : i32, ptr
|
||||||
|
|
||||||
|
%10 = ptr.load %StringBuilder : ptr -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %10, append:%.str.0 -> void
|
||||||
|
|
||||||
|
%7 = ptr.load %x : ptr -> i32
|
||||||
|
ivy.msg.send to %10, append:%7 -> void
|
||||||
|
|
||||||
|
%8 = ivy.msg.send to %10, to-string -> #ivy.id
|
||||||
|
|
||||||
|
%9 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
|
||||||
|
ivy.msg.send to %9, put:%8 -> void
|
||||||
|
|
||||||
|
func.return : ()
|
||||||
|
}
|
||||||
|
}
|
||||||
63
doc/mie/sample/Simple.3.mie
Normal file
63
doc/mie/sample/Simple.3.mie
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
meta.source-filename "Simple.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
%cout = ivy.pool.ident @cout -> #ivy.pool-slot
|
||||||
|
%StringBuilder = ivy.pool.ident @std.lang.StringBuilder -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.str.0 = ivy.pool.string "Answer: " -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.sel.o-append = ivy.pool.selector append -> #ivy.pool-slot
|
||||||
|
%.sel.o-to-string = ivy.pool.selector to-string -> #ivy.pool-slot
|
||||||
|
%.sel.o-put = ivy.pool.selector put -> #ivy.pool-slot
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
%0 = i32.constant 32
|
||||||
|
%1 = i32.constant 64
|
||||||
|
%multmp = *ivy.MUL %0, %1 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH %multmp : i32
|
||||||
|
%y = ivy.bp-slot 0 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%2 = i32.constant 64
|
||||||
|
%3 = i32.constant 4
|
||||||
|
%divtmp = *ivy.DIV %2, %3 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH %divtmp : i32
|
||||||
|
%z = ivy.bp-slot 1 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%4 = *ivy.LDR-BP %y : #ivy.bp-slot -> i32
|
||||||
|
%5 = *ivy.LDR-BP %z : #ivy.bp-slot -> i32
|
||||||
|
%addtmp = *ivy.ADD %4, %5 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH %addtmp : i32
|
||||||
|
%x = ivy.bp-slot 2 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%10 = *ivy.LDR-POOL %StringBuilder : #ivy.pool-slot -> #ivy.id
|
||||||
|
|
||||||
|
%20 = *ivy.LDR-POOL %.sel.o-append : #ivy.pool-slot -> #ivy.id
|
||||||
|
%21 = *ivy.LDR-POOL %.str.0 : #ivy.pool-slot -> #ivy.id
|
||||||
|
*ivy.PUSH %21 : #ivy.id
|
||||||
|
*ivy.MSG-I %10, %20, 1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
%7 = *ivy.LDR-BP %x : ptr -> i32
|
||||||
|
*ivy.PUSH %7 : i32
|
||||||
|
%22 = *ivy.LDR-POOL %.sel.o-append : #ivy.pool-slot -> #ivy.id
|
||||||
|
*ivy.MSG-I %10, %22, 1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
%23 = *ivy.LDR-POOL %.sel.o-to-string : #ivy.pool-slot -> #ivy.id
|
||||||
|
%8 = *ivy.MSG-I %10, %23, 0 : (#ivy.id, #ivy.id, i32) -> #ivy.id
|
||||||
|
|
||||||
|
%9 = *ivy.LDR-POOL %cout : #ivy.pool-slot -> #ivy.id
|
||||||
|
%24 = *ivy.LDR-POOL %.sel.o-put : #ivy.pool-slot -> #ivy.id
|
||||||
|
|
||||||
|
*ivy.PUSH %8 : #ivy.id
|
||||||
|
|
||||||
|
*ivy.MSG-I %9, %24, 1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
*ivy.RET-N : ()
|
||||||
|
}
|
||||||
|
}
|
||||||
62
doc/mie/sample/Simple.4.mie
Normal file
62
doc/mie/sample/Simple.4.mie
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
meta.source-filename "Simple.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
%cout = ivy.pool.ident @cout -> #ivy.pool-slot
|
||||||
|
%StringBuilder = ivy.pool.ident @std.lang.StringBuilder -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.str.0 = ivy.pool.string "Answer: " -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.sel.o-append = ivy.pool.selector append -> #ivy.pool-slot
|
||||||
|
%.sel.o-to-string = ivy.pool.selector to-string -> #ivy.pool-slot
|
||||||
|
%.sel.o-put = ivy.pool.selector put -> #ivy.pool-slot
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
%0 = i32.constant 32
|
||||||
|
%1 = i32.constant 64
|
||||||
|
%multmp = *ivy.MUL %0, %1 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH %multmp : i32
|
||||||
|
%y = ivy.bp-slot 0 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%2 = i32.constant 64
|
||||||
|
%3 = i32.constant 4
|
||||||
|
%divtmp = *ivy.DIV %2, %3 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH %divtmp : i32
|
||||||
|
%z = ivy.bp-slot 1 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%4 = *ivy.LDR %y : #ivy.bp-slot -> i32
|
||||||
|
%5 = *ivy.LDR %z : #ivy.bp-slot -> i32
|
||||||
|
%addtmp = *ivy.ADD %4, %5 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH %addtmp : i32
|
||||||
|
%x = ivy.bp-slot 2 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%10 = *ivy.LDR %StringBuilder : #ivy.pool-slot -> #ivy.id
|
||||||
|
|
||||||
|
%20 = *ivy.LDR %.sel.o-append : #ivy.pool-slot -> #ivy.id
|
||||||
|
%21 = *ivy.LDR %.str.0 : #ivy.pool-slot -> #ivy.id
|
||||||
|
*ivy.PUSH %21 : #ivy.id
|
||||||
|
*ivy.MSG %10, %20, 1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
%7 = *ivy.LDR %x : ptr -> i32
|
||||||
|
*ivy.PUSH %7 : i32
|
||||||
|
*ivy.MSG %10, %20, 1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
%23 = *ivy.LDR %.sel.o-to-string : #ivy.pool-slot -> #ivy.id
|
||||||
|
%8 = *ivy.MSG %10, %23, 0 : (#ivy.id, #ivy.id, i32) -> #ivy.id
|
||||||
|
|
||||||
|
%9 = *ivy.LDR %cout : #ivy.pool-slot -> #ivy.id
|
||||||
|
%24 = *ivy.LDR %.sel.o-put : #ivy.pool-slot -> #ivy.id
|
||||||
|
|
||||||
|
*ivy.PUSH %8 : #ivy.id
|
||||||
|
|
||||||
|
*ivy.MSG %9, %24, 1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
*ivy.RET-N : ()
|
||||||
|
}
|
||||||
|
}
|
||||||
68
doc/mie/sample/Simple.5.mie
Normal file
68
doc/mie/sample/Simple.5.mie
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
meta.source-filename "Simple.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.package-ref "std.io"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
%cout = ivy.pool.ident @cout -> #ivy.pool-slot
|
||||||
|
%StringBuilder = ivy.pool.ident @std.lang.StringBuilder -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.str.0 = ivy.pool.string "Answer: " -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.sel.o-append = ivy.pool.selector append -> #ivy.pool-slot
|
||||||
|
%.sel.o-to-string = ivy.pool.selector to-string -> #ivy.pool-slot
|
||||||
|
%.sel.o-put = ivy.pool.selector put -> #ivy.pool-slot
|
||||||
|
|
||||||
|
%.i.0 = i32.constant 0
|
||||||
|
%.i.1 = i32.constant 1
|
||||||
|
%.i.4 = i32.constant 4
|
||||||
|
%.i.32 = i32.constant 32
|
||||||
|
%.i.64 = i32.constant 64
|
||||||
|
|
||||||
|
ivy.init-text {
|
||||||
|
$X0 = *ivy.LDR %.i.32 -> i32
|
||||||
|
$X1 = *ivy.LDR %.i.64 -> i32
|
||||||
|
$X2 = *ivy.MUL $X0, $X1 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH $X2 : i32
|
||||||
|
%.bp.0 = ivy.bp-slot 0 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
$X4 = *ivy.LDR %.i.64 -> i32
|
||||||
|
$X5 = *ivy.LDR %.i.4 -> i32
|
||||||
|
$X6 = *ivy.DIV $X4, $X5 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH $X6 : i32
|
||||||
|
%.bp.1 = ivy.bp-slot 1 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
$X8 = *ivy.LDR %.bp.0 : #ivy.bp-slot -> i32
|
||||||
|
$X9 = *ivy.LDR %.bp.1 : #ivy.bp-slot -> i32
|
||||||
|
$X10 = *ivy.ADD $X8, $X9 : (i32, i32) -> i32
|
||||||
|
|
||||||
|
*ivy.PUSH $X10 : i32
|
||||||
|
%.bp.2 = ivy.bp-slot 2 -> #ivy.bp-slot
|
||||||
|
|
||||||
|
%10 = *ivy.LDR %StringBuilder : #ivy.pool-slot -> #ivy.id
|
||||||
|
|
||||||
|
%20 = *ivy.LDR %.sel.o-append : #ivy.pool-slot -> #ivy.id
|
||||||
|
%21 = *ivy.LDR %.str.0 : #ivy.pool-slot -> #ivy.id
|
||||||
|
*ivy.PUSH %21 : #ivy.id
|
||||||
|
*ivy.MSG %10, %20, %.i.1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
%7 = *ivy.LDR %.bp.2 : ptr -> i32
|
||||||
|
*ivy.PUSH %7 : i32
|
||||||
|
*ivy.MSG %10, %20, %.i.1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
%23 = *ivy.LDR %.sel.o-to-string : #ivy.pool-slot -> #ivy.id
|
||||||
|
%8 = *ivy.MSG %10, %23, %.i.0 : (#ivy.id, #ivy.id, i32) -> #ivy.id
|
||||||
|
|
||||||
|
%9 = *ivy.LDR %cout : #ivy.pool-slot -> #ivy.id
|
||||||
|
%24 = *ivy.LDR %.sel.o-put : #ivy.pool-slot -> #ivy.id
|
||||||
|
|
||||||
|
*ivy.PUSH %8 : #ivy.id
|
||||||
|
|
||||||
|
*ivy.MSG %9, %24, %.i.1 : (#ivy.id, #ivy.id, i32) -> void
|
||||||
|
|
||||||
|
*ivy.RET-N : ()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
data @cout = external global id
|
|
||||||
|
|
||||||
data @.str.0 = str "less"
|
|
||||||
data @.str.1 = str "more"
|
|
||||||
data @.str.2 = str "equal"
|
|
||||||
|
|
||||||
define void @init(id %self, id %0) static {
|
|
||||||
entry:
|
|
||||||
%x = alloca id
|
|
||||||
store i32 #2, ptr %x
|
|
||||||
|
|
||||||
%y = alloca id
|
|
||||||
store i32 #3, ptr %y
|
|
||||||
|
|
||||||
%1 = load i32, ptr %x
|
|
||||||
%2 = load i32, ptr %y
|
|
||||||
%3 = cmp lt i32 %1, %2
|
|
||||||
br i1 %3, label %if.true, label %if.false
|
|
||||||
|
|
||||||
if.true:
|
|
||||||
%4 = load id, ptr @cout
|
|
||||||
%5 = load str, ptr @.str.0
|
|
||||||
msg void, id %4, @_M03putE [str %5]
|
|
||||||
br label %if.end
|
|
||||||
|
|
||||||
if.false:
|
|
||||||
%6 = load i32, ptr %x
|
|
||||||
%7 = load i32, ptr %y
|
|
||||||
%8 = cmp gt i32 %6, %7
|
|
||||||
br i1 %8, label %if.true.0, label %if.false.0
|
|
||||||
|
|
||||||
if.true.0:
|
|
||||||
%9 = load id, ptr @cout
|
|
||||||
%10 = load str, ptr @.str.1
|
|
||||||
msg void, id %9, @_M03putE [str %10]
|
|
||||||
br label %if.end
|
|
||||||
|
|
||||||
if.false.0:
|
|
||||||
%11 = load id, ptr @cout
|
|
||||||
%12 = load str, ptr @.str.2
|
|
||||||
msg void, id %11, @_M03putE [str %12]
|
|
||||||
br label %if.end
|
|
||||||
|
|
||||||
if.end:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
y = 1 + 2 * 3 / 4 * 5 - 6 + 7 multiply-by:2.
|
y = -1 + 2 * 3 / 4 * 5 - 6 + 7 multiply-by:2.
|
||||||
z = w = 2 + 3 multiply-by:2.
|
z = w = 2 + 3 multiply-by:2.
|
||||||
x = (((1 + 2 * 3) multiply-by:3) add: 5) + 2.
|
x = (((1 + 2 * 3) multiply-by:3) add: 5) + 2.
|
||||||
x = ((1 + 2 * 3) multiply-by:3).
|
x = ((1 + 2 * 3) multiply-by:3).
|
||||||
@@ -13,7 +13,7 @@ m = xz multiply(by:3 add:2) squared.
|
|||||||
|
|
||||||
m = xz multiply(by:3 add:2); squared.
|
m = xz multiply(by:3 add:2); squared.
|
||||||
|
|
||||||
x = OrderedCollection new
|
x = Ordered-Collection new
|
||||||
add: 2;
|
add: 2;
|
||||||
add: 4;
|
add: 4;
|
||||||
add: 6;
|
add: 6;
|
||||||
@@ -21,7 +21,7 @@ x = OrderedCollection new
|
|||||||
|
|
||||||
age = Person new(name:"John Doe", age:34)
|
age = Person new(name:"John Doe", age:34)
|
||||||
set-age:144 in-unit:"months";
|
set-age:144 in-unit:"months";
|
||||||
ageInMonths.
|
age-in-months.
|
||||||
|
|
||||||
x = 5.
|
x = 5.
|
||||||
q = 10 if x > 2 else 20.
|
q = 10 if x > 2 else 20.
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
data @cout = external global id
|
ivy.module @test {
|
||||||
|
%cout = ivy.global-ref @cout
|
||||||
|
|
||||||
data @.str.0 = str "hello"
|
ivy.init-text {
|
||||||
|
%str = ivy.str.constant "hello"
|
||||||
|
%.str.0 = ivy.str.constant "done"
|
||||||
|
|
||||||
define void @init() static {
|
ivy.for-each %c in %str {
|
||||||
entry:
|
ivy.msg to %cout, -put:%c
|
||||||
%0 = load str, ptr @.str.0
|
}
|
||||||
%str = alloca id
|
|
||||||
store str %0, ptr %str
|
|
||||||
|
|
||||||
%1 = load id, ptr %str
|
ivy.msg to %cout, -put:%.str.0
|
||||||
%for.it = msg id, id %1, @_M8iteratorE
|
|
||||||
br label %for.cond
|
|
||||||
for.cond:
|
|
||||||
%for.value = msg id, id %for.it, @_M5valueE
|
|
||||||
%for.finished = cmp eq id %for.value, null
|
|
||||||
br i1 %for.finished, label %for.end, label %for.body
|
|
||||||
for.body:
|
|
||||||
%c = alloca id
|
|
||||||
store id %for.value, ptr %c
|
|
||||||
|
|
||||||
%2 = load id, ptr @cout
|
}
|
||||||
%3 = load id, ptr %c
|
|
||||||
msg void, id %2, @_M03putE [ id %3 ]
|
|
||||||
br label %for.inc
|
|
||||||
for.inc:
|
|
||||||
msg void, id %for.it, @_M8moveNextE
|
|
||||||
br label %for.cond
|
|
||||||
for.end:
|
|
||||||
ret void
|
|
||||||
}
|
}
|
||||||
|
|||||||
562
doc/sample/Person.2.im
Normal file
562
doc/sample/Person.2.im
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
/* example.im - An example Ivy Implementation source file */
|
||||||
|
|
||||||
|
package net.doorstuck.test
|
||||||
|
|
||||||
|
use std.io
|
||||||
|
|
||||||
|
-- Anything after a double hypen is ignored by the compiler
|
||||||
|
/*
|
||||||
|
Multi
|
||||||
|
Line
|
||||||
|
Comment
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
classes also double up as protocols.
|
||||||
|
|
||||||
|
any class can "pretend" to be another class by responding to the same
|
||||||
|
messages that the base class understands.
|
||||||
|
|
||||||
|
for example, by implementing all the messages that the Package class
|
||||||
|
understands, your class is said to implement the Package protocol,
|
||||||
|
allowing package-specific syntax (i.e. indexing and dot syntax)
|
||||||
|
to be used with your class.
|
||||||
|
|
||||||
|
there are two standard messages that complement this behaviour:
|
||||||
|
-is: takes a Class parameter, and returns true if the recipient
|
||||||
|
is an instance of the given Class.
|
||||||
|
-implements: takes a Class parameter, and returns true if the recipient
|
||||||
|
understands all of the messages that the parameter class
|
||||||
|
understands.
|
||||||
|
**/
|
||||||
|
class Person [
|
||||||
|
/**
|
||||||
|
A class is made up of the following components:
|
||||||
|
- a set of zero of more member variables
|
||||||
|
these can only be accessed by methods (not by functions) using the
|
||||||
|
self variable and the -> operator. member variables do not need
|
||||||
|
to be declared before they are used. assigning to a member variable
|
||||||
|
for the first time automatically "creates" it, and trying to access
|
||||||
|
a member variable that hasn't been assigned to will return null.
|
||||||
|
- a set of zero or more methods.
|
||||||
|
methods are procedure/sub-routines (a list of expressions evaluated
|
||||||
|
in order) executed in response to a particular message received by an
|
||||||
|
object. every method declares what sort of message it responds to.
|
||||||
|
- a set of zero or more functions.
|
||||||
|
functions are exactly like methods, except that they are executed in
|
||||||
|
response to messages sent to the class itself, rather than to an
|
||||||
|
instance of the class.
|
||||||
|
- a set of zero or more properties.
|
||||||
|
a property is similar to a member variable, with the following key
|
||||||
|
differences:
|
||||||
|
1) they are accessed using the . (dot) operator rather than the ->
|
||||||
|
(arrow) operator.
|
||||||
|
2) they can be accessed from outside the class.
|
||||||
|
3) they can (but don't have to) invoke blocks of code in response to
|
||||||
|
attempts to read from or assign to them.
|
||||||
|
4) they can be made read-write, read-only, or write-only.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
every method and function begins with a kebab, or message signature.
|
||||||
|
So called due to the preceding hyphen (for methods) or plus
|
||||||
|
(for functions) and the kebab-case convention used for message and
|
||||||
|
parameter names.
|
||||||
|
|
||||||
|
methods and functions are called in response to messages, and the kebab
|
||||||
|
defines exactly what message the method/function should be called for.
|
||||||
|
|
||||||
|
a message can have:
|
||||||
|
1) a name and zero or more parameters; or
|
||||||
|
2) no name and one or more parameters.
|
||||||
|
|
||||||
|
if a message has a name AND parameters, the parameters are listed
|
||||||
|
within parentheses and separated by commas.
|
||||||
|
|
||||||
|
if a message has parameters but no name, the parameters are listed
|
||||||
|
with no surrounding symbols and are separated only by whitespace.
|
||||||
|
|
||||||
|
every parameter has a label and an identifier. the label determines what
|
||||||
|
name needs to be specified before the parameter value when sending a
|
||||||
|
message, and forms part of the API. in contrast, the identifier is
|
||||||
|
simply the variable name that is used to access the parameter value
|
||||||
|
within the method/function, and is only used internally.
|
||||||
|
|
||||||
|
a parameter MUST have an identifier, but a label can be omitted by
|
||||||
|
specifying an _ (underscore) as the label.
|
||||||
|
|
||||||
|
when a method/function body has more than one expression, the
|
||||||
|
expressions must be surrounded by [] (square bracket block delimiters).
|
||||||
|
**/
|
||||||
|
-init(name:name, age:age) [
|
||||||
|
self->name = name.
|
||||||
|
self->age = age
|
||||||
|
]
|
||||||
|
|
||||||
|
/* if a method/function only has a single expression body, a | (pipe)
|
||||||
|
can be used between the kebab and body, and the body will automatically
|
||||||
|
end after one expression. */
|
||||||
|
-test(param:data, _:extra) | cout put:'Received {data}, {extra}'.
|
||||||
|
|
||||||
|
-name | ^self->name.
|
||||||
|
|
||||||
|
-age | ^self->age.
|
||||||
|
|
||||||
|
-age-in-months | ^self->age * 12.
|
||||||
|
|
||||||
|
-set-name:name | self->name = name.
|
||||||
|
|
||||||
|
-set-age:age | self->age = age.
|
||||||
|
|
||||||
|
-set-age:age in-unit:units [
|
||||||
|
match units [
|
||||||
|
$years => self->age = age,
|
||||||
|
$months => self->age = age / 12,
|
||||||
|
$days => self->age = age / 365,
|
||||||
|
_ => self->age = 0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
-get-age-in-units:units [
|
||||||
|
^match units [
|
||||||
|
$years => self->age,
|
||||||
|
$months => self->age / 12,
|
||||||
|
$days => self->age / 365,
|
||||||
|
_ => 0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
+create-with-name:name [
|
||||||
|
^Person new(name:name, age:32)
|
||||||
|
]
|
||||||
|
|
||||||
|
/* Properties are defined by a bare identifier (with no prefixes, so not
|
||||||
|
a kebab) followed by a pipe.
|
||||||
|
They accomplish two things:
|
||||||
|
1) they make it easy to synthesize the -get: and -put:at: messages
|
||||||
|
that the package dot syntax requires.
|
||||||
|
2) they allow you to implement getters and setters that are used
|
||||||
|
when someone attempts to access your object's data.
|
||||||
|
|
||||||
|
The contents of a property looks a bit like a package, but it has a few
|
||||||
|
special rules:
|
||||||
|
1) every value must have an associated key; and
|
||||||
|
2) the only keys that can be used are `get` and `set` (this is the only
|
||||||
|
instance where reserved keywords can be used as keys in a package).
|
||||||
|
|
||||||
|
In this case, the getter has been set to a variable. To facilitate this
|
||||||
|
functionality, the compiler converts this to a lambda of the form
|
||||||
|
[ ^self->val ]
|
||||||
|
that will be evaluated when the getter is invoked
|
||||||
|
|
||||||
|
Similarly, the compiler synthesizes a lambda for the setter as well.
|
||||||
|
Here, the expression
|
||||||
|
self->val = value
|
||||||
|
is converted to the lambda
|
||||||
|
[ :x | self->val = x ]
|
||||||
|
*/
|
||||||
|
example-property-a | get => self->val, set => self->val = value.
|
||||||
|
|
||||||
|
/* Without the lambda synthesis, the property would look like this:
|
||||||
|
Note that this is the only time it is legal to access private fields
|
||||||
|
via `self` from a lambda. */
|
||||||
|
example-property-b |
|
||||||
|
get => [ ^self->val ],
|
||||||
|
set => [ :x | self->val = x ].
|
||||||
|
|
||||||
|
/* The `get` element of a property doesn't have to be a lambda, it can
|
||||||
|
be any value. When the property is accessed, the value provided will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
If either the `set` or `get` elements are not provided, the property
|
||||||
|
becomes read-only or write-only respectively */
|
||||||
|
example-property-c | get => 42.
|
||||||
|
|
||||||
|
/* A property can also be configured to act just like a regular variable,
|
||||||
|
by setting the getter and setters to default implementations.
|
||||||
|
|
||||||
|
The default getter will return the value of a private member variable
|
||||||
|
named by prepending "p-" to the property name (p-example-property-d in
|
||||||
|
this case).
|
||||||
|
|
||||||
|
Similarly, the default setter will set the value of a private member
|
||||||
|
variable named by prepending "p-" to the property name
|
||||||
|
(p-example-property-d in this case) to the value provided to the setter. */
|
||||||
|
example-property-d (get, set)
|
||||||
|
|
||||||
|
/* Just like in the earlier examples, either `get` or `set` can be omitted
|
||||||
|
to create a write-only or read-only property respectively */
|
||||||
|
example-property-e (get)
|
||||||
|
]
|
||||||
|
|
||||||
|
p1 = Person new(name:'John Doe', age:34).
|
||||||
|
p1 set-age:100 in-unit:$months.
|
||||||
|
|
||||||
|
p1 test(param:'Hello', 'World').
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
i = 0.
|
||||||
|
while i < 100 [
|
||||||
|
cout put:'Count is {i}'.
|
||||||
|
i += 2
|
||||||
|
]
|
||||||
|
|
||||||
|
for x in 0 to:100 step:2 [
|
||||||
|
cout put:'Count is {x}'
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
a lambda's parameters are *always* unlabeled, and the underscore (_) before
|
||||||
|
the label colon (:) is unnecessary.
|
||||||
|
**/
|
||||||
|
0 to:100 step:2 do:[ :i | cout put:'Count: {i}' ].
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
lambdas can capture state from the context in which they are created.
|
||||||
|
|
||||||
|
a lambda can reference any local variable that is accessible at the point
|
||||||
|
it is created. if a variable from such a context is referenced, its value
|
||||||
|
is captured at the point the lambda is constructed. the value of the
|
||||||
|
variable is copied into the lambda.
|
||||||
|
|
||||||
|
this means that, if a lambda references a variable in the outer context,
|
||||||
|
and the value of that variable changes between the lambda being created
|
||||||
|
and the lambda being executed, that change will not be reflected within
|
||||||
|
the lambda.
|
||||||
|
|
||||||
|
because the value of captured variables is copied into the lambda, it is
|
||||||
|
safe for a method to return a lambda that references variables in its
|
||||||
|
local context.
|
||||||
|
**/
|
||||||
|
q = 32.
|
||||||
|
l = [ cout put:'Value of q is {q}' ]. /* value of `q` is captured here */
|
||||||
|
q = 64.
|
||||||
|
_ = l call. /* prints 'Value of q is 32' */
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
j = 32.
|
||||||
|
|
||||||
|
/**
|
||||||
|
expressions are terminated with a newline.
|
||||||
|
an expression can be written across multiple lines by using
|
||||||
|
the _ (underscore) line continuation character.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
keyword messages have a lower precedence than all non-assignment
|
||||||
|
binary operators, so (i < j) will be evaluated first, and
|
||||||
|
if:else: will be sent to the result.
|
||||||
|
**/
|
||||||
|
|
||||||
|
i < j
|
||||||
|
if:[ cout put:'True!' ]
|
||||||
|
else:[ cout put:'False!' ].
|
||||||
|
|
||||||
|
if i < j [
|
||||||
|
cout put:'True!'
|
||||||
|
]
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
pkg = {}.
|
||||||
|
|
||||||
|
/**
|
||||||
|
Packages can be indexed via integer or string. If a package is index with a
|
||||||
|
variable, the value of the variable is used as the index.
|
||||||
|
**/
|
||||||
|
|
||||||
|
pkg[0] = 16.
|
||||||
|
|
||||||
|
/* All of these accesses are equivalent */
|
||||||
|
pkg['x'] = 32.
|
||||||
|
pkg.x = 32.
|
||||||
|
pkg at:'x' put:32.
|
||||||
|
|
||||||
|
index = 'x'.
|
||||||
|
pkg[index] = 32.
|
||||||
|
pkg at:index put:32.
|
||||||
|
|
||||||
|
/**
|
||||||
|
this syntax, and the pkg.* instructions that it translates to, is
|
||||||
|
implemented behind-the-scenes by sending messages to the package.
|
||||||
|
|
||||||
|
if your custom object implements this protocol, package syntax can be used
|
||||||
|
on it too.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
these are the same packages used to store Classes and global variables.
|
||||||
|
for example, the std package is a regular package object, and you can use
|
||||||
|
package syntax on it or even send it messages.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/* integer constants can be written in all sorts of interesting formats */
|
||||||
|
i = 100.
|
||||||
|
i = 0x100.
|
||||||
|
i = 0200.
|
||||||
|
i = 0b1010101.
|
||||||
|
i = 1_000_000_000.
|
||||||
|
i = 100.25.
|
||||||
|
|
||||||
|
/* tuples can be used to create a set of values */
|
||||||
|
|
||||||
|
tuple = (32, 'a string').
|
||||||
|
|
||||||
|
/**
|
||||||
|
they are similar to packages, except they only support consecutive integer
|
||||||
|
indices, and you cannot specify the indices when creating a tuple.
|
||||||
|
|
||||||
|
the main purpose of tuples is to allow unwrapping of iterator variables in
|
||||||
|
for loops.
|
||||||
|
**/
|
||||||
|
|
||||||
|
for (key, val) in pkg [
|
||||||
|
cout put:'{key} -> {val}'
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
any object can be the target of a for-loop, as long as it meets one of the
|
||||||
|
following criteria:
|
||||||
|
a) is an Iterator object; or
|
||||||
|
b) implements the Iterator protocol; or
|
||||||
|
c) understands the -get-iterator message, and returns an object that itself
|
||||||
|
conforms to a) or b)
|
||||||
|
**/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
underscore (_) is used as a placeholder during assignment.
|
||||||
|
it can only appear on the left of an assignment, and anything
|
||||||
|
assigned to it is discarded.
|
||||||
|
*/
|
||||||
|
_ = 3 * 2.
|
||||||
|
|
||||||
|
/* it is mostly used with pattern-matching and destructuring. */
|
||||||
|
|
||||||
|
a = (32, 64).
|
||||||
|
(_, v) = a.
|
||||||
|
|
||||||
|
/* v is now equal to 64 */
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
try [
|
||||||
|
v = Int parse:'342'
|
||||||
|
] catch ($err:number-format, err) [
|
||||||
|
cout put:'Cannot parse integer string ({err})'
|
||||||
|
] catch (_, err) [
|
||||||
|
cout put:'Unknown error occurred ({err})'
|
||||||
|
]
|
||||||
|
|
||||||
|
/* equivalent 'pure' syntax */
|
||||||
|
|
||||||
|
[ v = Int parse:'342' ]
|
||||||
|
on:$err:number-format do:[ :err :data |
|
||||||
|
cout put:'Cannot parse integer string ({err})'
|
||||||
|
];
|
||||||
|
on-error:[ :err :data |
|
||||||
|
cout put:'Error {err} occurred ({data})'
|
||||||
|
];
|
||||||
|
call.
|
||||||
|
|
||||||
|
v = 5
|
||||||
|
squared
|
||||||
|
squared
|
||||||
|
squared.
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
x = 32.
|
||||||
|
/* a whole bunch of ways of doing conditionals using lambdas and messages */
|
||||||
|
[ cout put:'Hello, world!' ] if:x > 10.
|
||||||
|
[ cout put:'Hello, world!' ] unless:x <= 10.
|
||||||
|
|
||||||
|
/* and the equivalent 'fancy' syntax */
|
||||||
|
|
||||||
|
cout put:'Hello, world!' if x > 10.
|
||||||
|
-- cout put:'Hello, world!' unless x <= 10.
|
||||||
|
|
||||||
|
/**
|
||||||
|
NOTE that keywords (if, try, and so on) can still be used as message
|
||||||
|
parameter names. however, they cannot be used as message names.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Order of execution (precedence) for expression elements (listed from highest
|
||||||
|
to lowest precedence). elements that appear on the same list item have equal
|
||||||
|
precedence. in these cases, their associativity determines the order of
|
||||||
|
execution.
|
||||||
|
|
||||||
|
- binary operators
|
||||||
|
- package-access (.)
|
||||||
|
- self-access (->)
|
||||||
|
- unary operators
|
||||||
|
- boolean NOT (not)
|
||||||
|
- bitwise NOT (~)
|
||||||
|
- binary operators
|
||||||
|
- Type check operator (is, is not)
|
||||||
|
- Protocol check operator (understands)
|
||||||
|
- unary messages, complex messages
|
||||||
|
- binary operators
|
||||||
|
- multiplication (*)
|
||||||
|
- division (/)
|
||||||
|
- modulo (%)
|
||||||
|
- addition (+)
|
||||||
|
- subtraction (-)
|
||||||
|
- bitwise shift (<<, >>)
|
||||||
|
- comparison (<, >, <=, >=)
|
||||||
|
- (in)equality (==, !=)
|
||||||
|
- bitwise AND (&)
|
||||||
|
- bitwise XOR (^)
|
||||||
|
- bitwise OR (|)
|
||||||
|
- boolean AND (and)
|
||||||
|
- boolean OR (or)
|
||||||
|
- cascade (;)
|
||||||
|
- inline if-else
|
||||||
|
- keyword messages
|
||||||
|
- binary operators
|
||||||
|
- assignment by product, quotient, and remainder (*=, /=, %=)
|
||||||
|
- assignment by sum and difference (+=, -=)
|
||||||
|
- assignment by bitwise shift (<<=, >>=)
|
||||||
|
- assignment by bitwise AND, XOR, and OR (&=, ^=, |=)
|
||||||
|
- assignment (=)
|
||||||
|
**/
|
||||||
|
|
||||||
|
p1
|
||||||
|
set-age:2 squared squared + 4 squared multiply(by:2, add:4 + 1 * 3)
|
||||||
|
in:'mon' + 'ths'.
|
||||||
|
(p1
|
||||||
|
set-age:(((2 squared) squared) + ((4 squared) multiply(by:2, add:(4 + (1 * 3)))))
|
||||||
|
in:('mon' + 'ths')).
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/* how about package comprehension? */
|
||||||
|
|
||||||
|
/**
|
||||||
|
these two lines both construct a package containing all even numbers between
|
||||||
|
0 and 100 incremented by 1
|
||||||
|
|
||||||
|
the first one uses fancy list/package comprehension syntax.
|
||||||
|
the second one uses pure message/lambda syntax.
|
||||||
|
**/
|
||||||
|
data = { x + 1 for x in 0 to:100 if (x % 2) == 0 }.
|
||||||
|
data = (0 to: 100) select:[ :x | ^(x % 2) == 0 ] collect:[ :x | ^x + 1 ].
|
||||||
|
|
||||||
|
/**
|
||||||
|
for a package comprehension that follows this template:
|
||||||
|
EXPRESSION for VARIABLE in COLLECTION if CONDITION
|
||||||
|
the equivalent -select:collect: message would look something like this:
|
||||||
|
COLLECTION select:[ VARIABLE | CONDITION ] collect:[ VARIABLE | EXPRESSION ]
|
||||||
|
|
||||||
|
-select:collect: is used to create a new package by filtering and
|
||||||
|
transforming an existing package.
|
||||||
|
|
||||||
|
To apply a filter without a subsequent transform, you can use -select:
|
||||||
|
To apply a transformation with a filter beforehand, you can use -map:
|
||||||
|
**/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
packages also support a -map: message for constructing a new package by
|
||||||
|
manipulating an existing one.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
this example creates a package of all ints between 1 and 5 using a regular
|
||||||
|
collection literal, and then uses -map: to create a second package by
|
||||||
|
doubling each of the numbers in the fist package.
|
||||||
|
**/
|
||||||
|
pkg1 = { 1, 2, 3, 4, 5 }.
|
||||||
|
pkg2 = { x * 2 for x in pkg1 }.
|
||||||
|
pkg2 = pkg1 map:[ :x | ^x * 2 ].
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
semicolon (;) is the cascade operator. it returns the recipient of the
|
||||||
|
previously sent message. it can be used to send multiple messages to a
|
||||||
|
single recipient.
|
||||||
|
**/
|
||||||
|
|
||||||
|
age = Person new(name:'John Doe', age:34);
|
||||||
|
set-age:144 in-unit:$months;
|
||||||
|
ageInMonths.
|
||||||
|
|
||||||
|
-- age now has the value 144
|
||||||
|
-- the same behaviour can be achieved by using do[...]
|
||||||
|
|
||||||
|
age = do [
|
||||||
|
x = Person new(name:'John Doe', age:34).
|
||||||
|
x set-age:144 in-unit:$months.
|
||||||
|
x ageInMonths
|
||||||
|
].
|
||||||
|
|
||||||
|
/**
|
||||||
|
this allows messages to be easily chained, without relying on the message
|
||||||
|
handler returning `self`.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
NOTE that cascade is a binary operator, and cannot be used without a
|
||||||
|
right-hand operand. otherwise, simply adding a semicolon to the end of an
|
||||||
|
expression would change the behaviour (and result) of the expression.
|
||||||
|
|
||||||
|
however, because cascade is a binary operator, it also supports implicit
|
||||||
|
line continuations.
|
||||||
|
|
||||||
|
for situations where you want to return the recipient after a chain of
|
||||||
|
cascaded messages, you can use the -yourself message, which is understood by
|
||||||
|
all objects by default and always returns the object itself->
|
||||||
|
**/
|
||||||
|
|
||||||
|
p1 = Person new(name:'John Doe', age:34);
|
||||||
|
set-age:100 in-unit:$months;
|
||||||
|
yourself.
|
||||||
|
|
||||||
|
/* p1 now contains the Person object */
|
||||||
|
/* again, with do[...] */
|
||||||
|
|
||||||
|
p1 = do [
|
||||||
|
x = Person new(name:'John Doe', age:34).
|
||||||
|
x set-age:100 in-unit:$months.
|
||||||
|
x
|
||||||
|
].
|
||||||
|
|
||||||
|
|
||||||
|
v = "Hello".
|
||||||
|
if v is String [
|
||||||
|
cout put:"v is a string!"
|
||||||
|
]
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Blocks are a bit like lambdas, except they are part of the context of the
|
||||||
|
code that uses them. They are essentially a way of evaluating multiple
|
||||||
|
statements in a place where a single statement is usually expected.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/* Blocks are delimited by do[...], and the return operator can be used within
|
||||||
|
them. When it is, the value that is 'returned' will become the value that
|
||||||
|
the block as a whole evaluates to. also, the result of the last expression
|
||||||
|
evaluated in a block will be taken as its overall value. */
|
||||||
|
val = do [
|
||||||
|
x = 3.
|
||||||
|
y = 2.
|
||||||
|
x * y
|
||||||
|
].
|
||||||
|
|
||||||
|
/* after this statement is executed, `val` will be equal to 6. */
|
||||||
|
|
||||||
@@ -48,7 +48,6 @@ class Person
|
|||||||
compatibility with lambdas.
|
compatibility with lambdas.
|
||||||
**/
|
**/
|
||||||
- init(name:name age:age)
|
- init(name:name age:age)
|
||||||
var x.
|
|
||||||
self::name = name.
|
self::name = name.
|
||||||
self::age = age!
|
self::age = age!
|
||||||
|
|
||||||
@@ -80,7 +79,7 @@ class Person
|
|||||||
_ => 0
|
_ => 0
|
||||||
end!
|
end!
|
||||||
|
|
||||||
/* Properties are defined using the $ symbol.
|
/* Properties are defined using the -> symbol.
|
||||||
They accomplish two things:
|
They accomplish two things:
|
||||||
1) they make it easy to synthesize the -get: and -put:at: messages
|
1) they make it easy to synthesize the -get: and -put:at: messages
|
||||||
that the package dot syntax requires.
|
that the package dot syntax requires.
|
||||||
@@ -109,7 +108,7 @@ class Person
|
|||||||
/* Without the lambda synthesis, the property would look like this:
|
/* Without the lambda synthesis, the property would look like this:
|
||||||
Note that this is the only time it is legal to access private fields
|
Note that this is the only time it is legal to access private fields
|
||||||
via `self` from a lambda. */
|
via `self` from a lambda. */
|
||||||
-> example-property |
|
-> example-property-2 |
|
||||||
get => [ ^self::val ],
|
get => [ ^self::val ],
|
||||||
set => [ :x | self::val = x ].
|
set => [ :x | self::val = x ].
|
||||||
|
|
||||||
@@ -119,23 +118,23 @@ class Person
|
|||||||
|
|
||||||
If either the `set` or `get` elements are not provided, the property
|
If either the `set` or `get` elements are not provided, the property
|
||||||
becomes read-only or write-only respectively */
|
becomes read-only or write-only respectively */
|
||||||
-> example-property-2 | get => 42.
|
-> example-property-3 | get => 42.
|
||||||
|
|
||||||
/* A property can also be configured to act just like a regular variable,
|
/* A property can also be configured to act just like a regular variable,
|
||||||
by setting the getter and setters to default implementations.
|
by setting the getter and setters to default implementations.
|
||||||
|
|
||||||
The default getter will return the value of a private member variable
|
The default getter will return the value of a private member variable
|
||||||
named by prepending two underscores to the property name
|
named by prepending two underscores to the property name
|
||||||
(__exampleProperty3 in this case).
|
(__example-property-4 in this case).
|
||||||
|
|
||||||
Similarly, the default setter will set the value of a private member
|
Similarly, the default setter will set the value of a private member
|
||||||
variable named by prepending two underscores to the property name
|
variable named by prepending two underscores to the property name
|
||||||
(__exampleProperty3 in this case) to the value provided to the setter. */
|
(__example-property-4 in this case) to the value provided to the setter. */
|
||||||
-> example-property-3 (get, set)
|
-> example-property-4 (get, set)
|
||||||
|
|
||||||
/* Just like in the earlier examples, either `get` or `set` can be omitted
|
/* Just like in the earlier examples, either `get` or `set` can be omitted
|
||||||
to create a write-only or read-only property respectively */
|
to create a write-only or read-only property respectively */
|
||||||
-> example-property-4 (get)
|
-> example-property-5 (get)
|
||||||
end
|
end
|
||||||
|
|
||||||
p1 = Person new(name:'John Doe', age:34).
|
p1 = Person new(name:'John Doe', age:34).
|
||||||
@@ -151,8 +150,8 @@ while i < 100 do
|
|||||||
i += 2
|
i += 2
|
||||||
end
|
end
|
||||||
|
|
||||||
for i in 0 to:100 step:2 do
|
for x in 0 to:100 step:2 do
|
||||||
cout put:'Count is {i}'
|
cout put:'Count is {x}'
|
||||||
end
|
end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,11 +222,11 @@ pkg[0] = 16.
|
|||||||
/* All of these accesses are equivalent */
|
/* All of these accesses are equivalent */
|
||||||
pkg['x'] = 32.
|
pkg['x'] = 32.
|
||||||
pkg->x = 32.
|
pkg->x = 32.
|
||||||
pkg put:32 at:'x'.
|
pkg at:'x' put:32.
|
||||||
|
|
||||||
index = 'x'.
|
index = 'x'.
|
||||||
pkg[index] = 32.
|
pkg[index] = 32.
|
||||||
pkg put:32 at:index.
|
pkg at:index put:32.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
this syntax, and the pkg.* instructions that it translates to, is
|
this syntax, and the pkg.* instructions that it translates to, is
|
||||||
@@ -274,7 +273,7 @@ end
|
|||||||
following criteria:
|
following criteria:
|
||||||
a) is an Iterator object; or
|
a) is an Iterator object; or
|
||||||
b) implements the Iterator protocol; or
|
b) implements the Iterator protocol; or
|
||||||
c) understands the -iterator message, and returns an object that itself
|
c) understands the -get-iterator message, and returns an object that itself
|
||||||
conforms to a) or b)
|
conforms to a) or b)
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -311,7 +310,7 @@ end
|
|||||||
on:$err:number-format do:[ :err :data |
|
on:$err:number-format do:[ :err :data |
|
||||||
cout put:'Cannot parse integer string ({err})'
|
cout put:'Cannot parse integer string ({err})'
|
||||||
];
|
];
|
||||||
onError:[ :err :data |
|
on-error:[ :err :data |
|
||||||
cout put:'Error {err} occurred ({data})'
|
cout put:'Error {err} occurred ({data})'
|
||||||
];
|
];
|
||||||
call.
|
call.
|
||||||
|
|||||||
@@ -1,36 +1,9 @@
|
|||||||
y = -1 + 2 * 3 / 4 * 5 - 6 + 7 multiply-by:2.
|
package net.doorstuck.test
|
||||||
z = w = 2 + 3 multiply-by:2.
|
|
||||||
x = (((1 + 2 * 3) multiply-by:3) add: 5) + 2.
|
|
||||||
x = ((1 + 2 * 3) multiply-by:3).
|
|
||||||
p = 5 multiply(by:3, add:(2 + 1)).
|
|
||||||
q = 10 squared squared.
|
|
||||||
|
|
||||||
p1
|
use std.io
|
||||||
set-age:2 squared squared + 4 squared multiply(by:2, add:4 + 1 * 3)
|
|
||||||
in:"mon" + "ths".
|
|
||||||
|
|
||||||
m = xz multiply(by:3 add:2) squared.
|
y = 32 * 64.
|
||||||
|
z = 64 / 4.
|
||||||
|
x = y + z.
|
||||||
|
|
||||||
m = xz multiply(by:3 add:2); squared.
|
cout put:'Answer: {x}'
|
||||||
|
|
||||||
x = Ordered-Collection new
|
|
||||||
add: 2;
|
|
||||||
add: 4;
|
|
||||||
add: 6;
|
|
||||||
yourself.
|
|
||||||
|
|
||||||
age = Person new(name:"John Doe", age:34)
|
|
||||||
set-age:144 in-unit:"months";
|
|
||||||
age-in-months.
|
|
||||||
|
|
||||||
x = 5.
|
|
||||||
q = 10 if x > 2 else 20.
|
|
||||||
q = if x > 2 then 10 else 20 end.
|
|
||||||
|
|
||||||
cout put:5 multiply(by:5, add:2) if x > 2.
|
|
||||||
|
|
||||||
if x > 2 then
|
|
||||||
cout put:"Greater"
|
|
||||||
else
|
|
||||||
cout put:"Less"
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.doorstuck.test
|
package net.doorstuck.test
|
||||||
|
|
||||||
s1 = 'hello world'
|
s1 = 'hello world'.
|
||||||
|
|
||||||
s2 = s1 map:[ :c | ^c uppercase ]
|
s2 = s1 map:[ :c | ^c uppercase ].
|
||||||
s3 = s1 map:[ :c | ^((c ordinal) + 1) to-char ]
|
s3 = s1 map:[ :c | ^((c ordinal) + 1) to-char ]
|
||||||
|
|||||||
96
doc/sample/Sum.2.mie
Normal file
96
doc/sample/Sum.2.mie
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
meta.source-filename "Sum.im"
|
||||||
|
|
||||||
|
ivy.package-scope "net.doorstuck.test"
|
||||||
|
|
||||||
|
ivy.module {
|
||||||
|
ivy.init-text {
|
||||||
|
%0 = ivy.str.constant "Finds the sum of a set of numbers."
|
||||||
|
|
||||||
|
%cout = ivy.global-ref @cout -> ptr
|
||||||
|
%1 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
|
||||||
|
ivy.send-msg to %1, put:%0 -> void
|
||||||
|
|
||||||
|
%sum = ptr.alloca i32 -> ptr
|
||||||
|
%sum.0 = i32.constant 0
|
||||||
|
|
||||||
|
ptr.store %sum.0, %sum : i32, ptr
|
||||||
|
|
||||||
|
scf.loop() -> void {
|
||||||
|
%2 = ivy.str.constant "Number (blank to finish): "
|
||||||
|
|
||||||
|
%3 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
|
||||||
|
ivy.send-msg to %3, put:%2 -> void
|
||||||
|
|
||||||
|
%4 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
ivy.send-msg to %3, flush -> void
|
||||||
|
|
||||||
|
%v = ptr.alloca i32 -> ptr
|
||||||
|
%5 = i32.constant 0
|
||||||
|
|
||||||
|
ptr.store %5, %v : i32, ptr
|
||||||
|
|
||||||
|
%input = ptr.alloca #ivy.id -> ptr
|
||||||
|
%cin = ivy.global-ref @cin -> ptr
|
||||||
|
|
||||||
|
%7 = ptr.load %cin : ptr -> #ivy.id
|
||||||
|
|
||||||
|
%8 = ivy.send-msg to %7, read-line -> #ivy.id
|
||||||
|
ptr.store %8, %input : #ivy.id, ptr
|
||||||
|
|
||||||
|
%9 = ptr.load %input : ptr -> #ivy.id
|
||||||
|
|
||||||
|
%String = ivy.global-ref @String -> ptr
|
||||||
|
%10 = ptr.load %String : ptr -> #ivy.id
|
||||||
|
|
||||||
|
%11 = ivy.send-msg to %10, new -> #ivy.id
|
||||||
|
|
||||||
|
%12 = ivy.cmp eq %9, %11 : (#ivy.id, #ivy.id) -> i1
|
||||||
|
scf.if %12 -> void {
|
||||||
|
scf.loop-break : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
%v = ptr.alloca #ivy.id -> ptr
|
||||||
|
|
||||||
|
%Int = ivy.global-ref @Int -> ptr
|
||||||
|
|
||||||
|
%13 = ptr.load %Int : ptr -> #ivy.id
|
||||||
|
%14 = ptr.load %input : ptr -> #ivy.id
|
||||||
|
%15 = ivy.send-msg to %12, parse:%14 -> #ivy.id
|
||||||
|
|
||||||
|
ptr.store %15, %v : #ivy.id, ptr
|
||||||
|
|
||||||
|
%16 = ptr.load %v : ptr -> #ivy.id
|
||||||
|
%17 = ivy.null-id : #ivy.id
|
||||||
|
|
||||||
|
%18 = ivy.cmp eq %16, %17 : (#ivy.id, #ivy.id) -> i1
|
||||||
|
|
||||||
|
scf.if %1 -> void {
|
||||||
|
%19 = ptr.load %cout : ptr -> #ivy.id
|
||||||
|
|
||||||
|
%StringBuilder = ivy.global-ref @StringBuilder -> ptr
|
||||||
|
%20 = ptr.load %StringBuilder : ptr -> #ivy.id
|
||||||
|
%21 = ivy.send-msg to %20, new -> #ivy.id
|
||||||
|
|
||||||
|
%22 = ptr.load %input : ptr -> #ivy.id
|
||||||
|
ivy.send-msg to %21, append:%22 -> void
|
||||||
|
|
||||||
|
%23 = ivy.str.constant " is not a valid number."
|
||||||
|
ivy.send-msg to %21, append:%23 -> void
|
||||||
|
|
||||||
|
%24 = ivy.send-msg to %21, to-string -> #ivy.id
|
||||||
|
ivy.send-msg to %19, put:%24 -> void
|
||||||
|
|
||||||
|
scf.loop-continue : ()
|
||||||
|
}
|
||||||
|
|
||||||
|
%25 = ptr.load %sum : ptr -> i32
|
||||||
|
%26 = ptr.load %v : ptr -> #ivy.id
|
||||||
|
%addtmp = ivy.add %25, %26 : (i32, #ivy.id) -> #ivy.id
|
||||||
|
ptr.store %addtmp, %sum : #ivy.id, ptr
|
||||||
|
|
||||||
|
scf.loop-continue : ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
var x = 2 + 3.
|
|
||||||
var y = x.
|
x = 3.
|
||||||
var z.
|
y = 0.
|
||||||
var (x, y) = (3, 4).
|
|
||||||
|
if x > 10 then
|
||||||
|
y = 4
|
||||||
|
else
|
||||||
|
y = 2
|
||||||
|
end
|
||||||
|
|||||||
@@ -229,6 +229,9 @@ static b_result generate_mie_ir(struct compile_ctx *ctx)
|
|||||||
static b_result build_block_isel_graph(
|
static b_result build_block_isel_graph(
|
||||||
struct compile_ctx *ctx, struct mie_func *func, struct mie_block *block)
|
struct compile_ctx *ctx, struct mie_func *func, struct mie_block *block)
|
||||||
{
|
{
|
||||||
|
printf("selecting %s.%s...\n", func->f_base.v_name.n_str,
|
||||||
|
block->b_base.v_name.n_str);
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&block->b_phi);
|
b_queue_entry *entry = b_queue_first(&block->b_phi);
|
||||||
while (entry) {
|
while (entry) {
|
||||||
struct mie_value *instr_v
|
struct mie_value *instr_v
|
||||||
@@ -254,9 +257,13 @@ static b_result build_block_isel_graph(
|
|||||||
struct mie_select_graph *graph = mie_select_builder_finish(ctx->select);
|
struct mie_select_graph *graph = mie_select_builder_finish(ctx->select);
|
||||||
|
|
||||||
if (ctx->flags & FLAG_SHOW_PRE_SELECT_GRAPH) {
|
if (ctx->flags & FLAG_SHOW_PRE_SELECT_GRAPH) {
|
||||||
|
char name[128];
|
||||||
|
snprintf(
|
||||||
|
name, sizeof name, "%s.%s.dot",
|
||||||
|
func->f_base.v_name.n_str, block->b_base.v_name.n_str);
|
||||||
printf("%s.%s instruction graph:\n", func->f_base.v_name.n_str,
|
printf("%s.%s instruction graph:\n", func->f_base.v_name.n_str,
|
||||||
block->b_base.v_name.n_str);
|
block->b_base.v_name.n_str);
|
||||||
mie_select_graph_dump_dot(graph);
|
mie_select_graph_dump_dot(graph, name);
|
||||||
mie_select_graph_destroy(graph);
|
mie_select_graph_destroy(graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,25 +9,32 @@ setlocal iskeyword+=-
|
|||||||
syn match ivyType /\<[A-Z]\{1,2}[a-z0-9]\+\(-\?[A-Z]\{1,2}[a-z0-9]\+\)*\>/
|
syn match ivyType /\<[A-Z]\{1,2}[a-z0-9]\+\(-\?[A-Z]\{1,2}[a-z0-9]\+\)*\>/
|
||||||
|
|
||||||
syn match ivySelectorLabel /\<[a-z][A-Za-z0-9-_]*\:/
|
syn match ivySelectorLabel /\<[a-z][A-Za-z0-9-_]*\:/
|
||||||
|
syn match ivySelectorLabel /\-[a-z][A-Za-z0-9-_]*\:/
|
||||||
|
syn match ivySelectorLabel /+[a-z][A-Za-z0-9-_]*\:/
|
||||||
"syn match ivySelectorLabel /\<\([a-z]\([A-Za-z0-9_]\+\)\:\(\:\)\@!\)\+/
|
"syn match ivySelectorLabel /\<\([a-z]\([A-Za-z0-9_]\+\)\:\(\:\)\@!\)\+/
|
||||||
syn match ivyUnnamedVariable /\<_\>/
|
|
||||||
|
|
||||||
syn match ivyAtomName /\$[a-z][a-z0-9_:/-]*\>/
|
syn match ivyAtomName /\$[a-z][a-z0-9_:/-]*\>/
|
||||||
syn match ivyWord /\<[a-z_][a-zA-Z0-9_]*\(-\?[a-zA-Z][a-zA-Z0-9_]*\)*\>\(\:\)\@!/
|
syn match ivyWord /\<[a-z_][a-zA-Z0-9_]*\(-\?[a-zA-Z][a-zA-Z0-9_]*\)*\>\(\:\)\@!/
|
||||||
|
|
||||||
|
syn match ivyUnnamedLabel /\s*(\?_:/
|
||||||
|
syn match ivyUnnamedVariable /\<_\>/
|
||||||
|
|
||||||
syn match ivyComplexMessageName /\<\zs[A-Za-z][A-Za-z0-9-_]\+\ze(/
|
syn match ivyComplexMessageName /\<\zs[A-Za-z][A-Za-z0-9-_]\+\ze(/
|
||||||
|
syn match ivyComplexMessageName /\-[A-Za-z][A-Za-z0-9-_]\+\ze(/
|
||||||
|
syn match ivyComplexMessageName /+[A-Za-z][A-Za-z0-9-_]\+\ze(/
|
||||||
"syn match ivyUnaryMessageName /-\s*[a-zA-z][a-zA-Z0-9_]\+\s*\n/
|
"syn match ivyUnaryMessageName /-\s*[a-zA-z][a-zA-Z0-9_]\+\s*\n/
|
||||||
syn match ivyUnaryMessageName /\(-\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*\n\)\@=/
|
syn match ivyUnaryMessageName /\(-\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*\n\)\@=/
|
||||||
syn match ivyUnaryMessageName /\(-\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*|\)\@=/
|
syn match ivyUnaryMessageName /\(-\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*|\)\@=/
|
||||||
syn match ivyUnaryMessageName /\(+\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*\n\)\@=/
|
syn match ivyUnaryMessageName /\(+\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*\n\)\@=/
|
||||||
syn match ivyUnaryMessageName /\(+\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*|\)\@=/
|
syn match ivyUnaryMessageName /\(+\s*\)\@<=[a-z][A-Za-z0-9-_]*\(\s*|\)\@=/
|
||||||
|
syn match ivyUnaryMessageName /\-[a-z][A-Za-z0-9-_]*\(\s*[\|\[]\)\@=/
|
||||||
|
syn match ivyUnaryMessageName /+[a-z][A-Za-z0-9-_]*\(\s*[\|\[]\)\@=/
|
||||||
syn match ivyPropertyName /\(->\s*\)\@<=[a-z][A-Za-z0-9-_]*/
|
syn match ivyPropertyName /\(->\s*\)\@<=[a-z][A-Za-z0-9-_]*/
|
||||||
|
|
||||||
syn match ivyLineContinuation /\\\n/
|
syn match ivyLineContinuation /\\\n/
|
||||||
|
|
||||||
" Modifiers
|
" Modifiers
|
||||||
|
|
||||||
syn match ivySelfVar /\<self\([^a-zA-Z0-9-_]\)\@=/
|
syn match ivySelfVar /\<self\([^a-zA-Z0-9_]\)\@=/
|
||||||
|
|
||||||
" we have to use syn match for keywords because any keyword can be used as a
|
" we have to use syn match for keywords because any keyword can be used as a
|
||||||
" label by adding : to the end, and adding : to iskeyword causes more problems
|
" label by adding : to the end, and adding : to iskeyword causes more problems
|
||||||
@@ -44,19 +51,23 @@ syn match ivyUseStmtIdentifier /\(use \)\@<=\([A-Za-z_][A-Za-z0-9_]*\)\(.\([A-Za
|
|||||||
|
|
||||||
" Operators/Punctuation
|
" Operators/Punctuation
|
||||||
syn match ivyBraces "[{}]" display
|
syn match ivyBraces "[{}]" display
|
||||||
syn match ivyBrackets "[[\]]" display
|
|
||||||
syn match ivyParens "[()]" display
|
syn match ivyParens "[()]" display
|
||||||
|
syn match ivyControlSymbols "[[\]]" display
|
||||||
|
syn match ivyControlSymbols "|" display
|
||||||
|
syn match ivyControlSymbols "\^" display
|
||||||
syn match ivyOpSymbols "\*" display
|
syn match ivyOpSymbols "\*" display
|
||||||
syn match ivyOpSymbols "::" display
|
|
||||||
syn match ivyOpSymbols "=\{1,2}" display
|
syn match ivyOpSymbols "=\{1,2}" display
|
||||||
syn match ivyOpSymbols ">\{1,2}" display
|
syn match ivyOpSymbols ">\{1,2}" display
|
||||||
syn match ivyOpSymbols "<\{1,2}" display
|
syn match ivyOpSymbols "<\{1,2}" display
|
||||||
syn match ivyOpSymbols "[+\-/*%&^!|<>;,]" display
|
syn match ivyOpSymbols "[\/*%&!<>;,]" display
|
||||||
syn match ivyOpSymbols "[+\-/*%&^!|<>]=" display
|
syn match ivyOpSymbols "[+\-/*%&!<>]=" display
|
||||||
|
syn match ivyOpSymbols "\s\+[\-+]\s\+" display
|
||||||
|
syn match ivyOpSymbols "\->" display
|
||||||
syn match ivyOtherSymbols "=>" display
|
syn match ivyOtherSymbols "=>" display
|
||||||
syn match ivyLogicSymbols "&&" display
|
syn match ivyLogicSymbols "&&" display
|
||||||
syn match ivyLogicSymbols "||" display
|
syn match ivyLogicSymbols "||" display
|
||||||
syn match ivyStatementSeparator "\.\s*" display
|
syn match ivyPackageAccessOperator "\." display
|
||||||
|
syn match ivyStatementSeparator "\.\s*\n" display
|
||||||
syn match ivyMessageTerminator "\![\s\n]\+" display
|
syn match ivyMessageTerminator "\![\s\n]\+" display
|
||||||
syn keyword ivyWordOperator is not understands and or
|
syn keyword ivyWordOperator is not understands and or
|
||||||
|
|
||||||
@@ -147,15 +158,14 @@ hi def link ivyStatement Statement
|
|||||||
hi def link ivyRepeat Repeat
|
hi def link ivyRepeat Repeat
|
||||||
hi def link ivyConditional Conditional
|
hi def link ivyConditional Conditional
|
||||||
hi def link ivySelectorLabel Tag
|
hi def link ivySelectorLabel Tag
|
||||||
hi def link ivyUnnamedLabel @variable.builtin
|
hi def link ivyUnnamedLabel Comment
|
||||||
hi def link ivyUnnamedVariable @variable.builtin
|
hi def link ivyUnnamedVariable Comment
|
||||||
hi def link ivyLambdaParameter @variable.builtin
|
hi def link ivyLambdaParameter @variable.builtin
|
||||||
hi def link ivyException Exception
|
hi def link ivyException Exception
|
||||||
|
|
||||||
hi def link ivyParens Delimiter
|
hi def link ivyParens Delimiter
|
||||||
hi def link ivyBraces Structure
|
hi def link ivyBraces Structure
|
||||||
hi def link ivyBrackets Define
|
hi def link ivyControlSymbols Keyword
|
||||||
hi def link ivyLambdaSymbols Define
|
|
||||||
|
|
||||||
hi def link ivyModifier StorageClass
|
hi def link ivyModifier StorageClass
|
||||||
hi def link ivyAccessModifier ivyModifier
|
hi def link ivyAccessModifier ivyModifier
|
||||||
@@ -176,6 +186,7 @@ hi def link ivyTypeOf ivyKeywordOperator
|
|||||||
hi def link ivyTypeOfOperand Typedef
|
hi def link ivyTypeOfOperand Typedef
|
||||||
hi def link ivyTypeOfError Error
|
hi def link ivyTypeOfError Error
|
||||||
hi def link ivyOpSymbols Operator
|
hi def link ivyOpSymbols Operator
|
||||||
|
hi def link ivyPackageAccessOperator Operator
|
||||||
hi def link ivyOtherSymbols Structure
|
hi def link ivyOtherSymbols Structure
|
||||||
hi def link ivyLogicSymbols Operator
|
hi def link ivyLogicSymbols Operator
|
||||||
hi def link ivyWordOperator Operator
|
hi def link ivyWordOperator Operator
|
||||||
|
|||||||
1
mie
Submodule
1
mie
Submodule
Submodule mie added at 937dc57c4e
@@ -1,15 +0,0 @@
|
|||||||
file(GLOB_RECURSE mie_sources *.c *.h include/mie/*.h)
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
set(rc_file ${CMAKE_CURRENT_SOURCE_DIR}/../res/win32/mie.rc)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (IVY_STATIC)
|
|
||||||
add_library(mie STATIC ${mie_sources} ${rc_file})
|
|
||||||
else ()
|
|
||||||
add_library(mie SHARED ${mie_sources} ${rc_file})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_include_directories(mie PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
|
||||||
target_link_libraries(mie Bluelib::Core Bluelib::Ds)
|
|
||||||
target_compile_definitions(mie PRIVATE MIE_EXPORT=1 MIE_STATIC=${IVY_STATIC})
|
|
||||||
14
mie/README
14
mie/README
@@ -1,14 +0,0 @@
|
|||||||
METACOMPUTE INSTRUCTION ENGINE
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Mie is an abstract virtual machine and intermediate representation manipulation
|
|
||||||
toolkit. It includes facilities for building, manipulating, and optimising
|
|
||||||
intermediate representations of programs, as well as converting IR to/from
|
|
||||||
different formats.
|
|
||||||
|
|
||||||
The Mie virtual machine features an infinite amount of memory and registers.
|
|
||||||
A Mie program can be emitted by a simple front-end compiler that makes use of
|
|
||||||
these infinite resources, and Mie's optimisers will convert this program into a
|
|
||||||
form that can efficiently use and re-use a more finite set of resources.
|
|
||||||
Finally, a Mie backend can convert the program into a concrete implementation
|
|
||||||
for a particular system.
|
|
||||||
283
mie/ctx.c
283
mie/ctx.c
@@ -1,283 +0,0 @@
|
|||||||
#include <blue/ds/hashmap.h>
|
|
||||||
#include <blue/ds/list.h>
|
|
||||||
#include <blue/ds/string.h>
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct ctx_int_cache_entry {
|
|
||||||
b_btree_node i_node;
|
|
||||||
struct mie_type i_type;
|
|
||||||
b_btree i_values;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ctx_int_value_cache_entry {
|
|
||||||
b_btree_node i_node;
|
|
||||||
struct mie_int i_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
B_BTREE_DEFINE_SIMPLE_INSERT(
|
|
||||||
struct ctx_int_cache_entry, i_node, i_type.t_width, put_cached_int_type)
|
|
||||||
B_BTREE_DEFINE_SIMPLE_GET(
|
|
||||||
struct ctx_int_cache_entry, unsigned int, i_node, i_type.t_width,
|
|
||||||
get_cached_int_type)
|
|
||||||
|
|
||||||
B_BTREE_DEFINE_SIMPLE_INSERT(
|
|
||||||
struct ctx_int_value_cache_entry, i_node, i_value.i_value,
|
|
||||||
put_cached_int_value)
|
|
||||||
B_BTREE_DEFINE_SIMPLE_GET(
|
|
||||||
struct ctx_int_value_cache_entry, int64_t, i_node, i_value.i_value,
|
|
||||||
get_cached_int_value)
|
|
||||||
|
|
||||||
struct mie_ctx *mie_ctx_create(void)
|
|
||||||
{
|
|
||||||
struct mie_ctx *out = malloc(sizeof *out);
|
|
||||||
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->ctx_true = MIE_CONST(mie_ctx_get_int(out, 1, 1));
|
|
||||||
out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1));
|
|
||||||
|
|
||||||
out->ctx_null = malloc(sizeof *out->ctx_null);
|
|
||||||
if (!out->ctx_null) {
|
|
||||||
mie_ctx_destroy(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_value_init(out->ctx_null, MIE_VALUE_NONE);
|
|
||||||
|
|
||||||
out->ctx_sel_cache = b_hashmap_create(free, free);
|
|
||||||
out->ctx_string_cache = b_hashmap_create(free, free);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_ctx_destroy(struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
ctx->ctx_true = NULL;
|
|
||||||
ctx->ctx_false = NULL;
|
|
||||||
|
|
||||||
b_btree_node *node = b_btree_first(&ctx->ctx_int_cache);
|
|
||||||
while (node) {
|
|
||||||
struct ctx_int_cache_entry *entry
|
|
||||||
= b_unbox(struct ctx_int_cache_entry, node, i_node);
|
|
||||||
b_btree_node *next = b_btree_next(node);
|
|
||||||
b_btree_delete(&ctx->ctx_int_cache, node);
|
|
||||||
|
|
||||||
b_btree_node *node2 = b_btree_first(&entry->i_values);
|
|
||||||
while (node2) {
|
|
||||||
struct ctx_int_value_cache_entry *value = b_unbox(
|
|
||||||
struct ctx_int_value_cache_entry, node2, i_node);
|
|
||||||
b_btree_node *next2 = b_btree_next(node2);
|
|
||||||
b_btree_delete(&entry->i_values, node2);
|
|
||||||
free(value);
|
|
||||||
node2 = next2;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(entry);
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t nr_types = sizeof ctx->ctx_types / sizeof ctx->ctx_types[0];
|
|
||||||
for (size_t i = 0; i < nr_types; i++) {
|
|
||||||
if (ctx->ctx_types[i]) {
|
|
||||||
mie_value_destroy(MIE_VALUE(ctx->ctx_types[i]));
|
|
||||||
ctx->ctx_types[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->ctx_null) {
|
|
||||||
mie_value_destroy(ctx->ctx_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_hashmap_unref(ctx->ctx_sel_cache);
|
|
||||||
|
|
||||||
free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *mie_ctx_get_type(struct mie_ctx *ctx, enum mie_type_id type_id)
|
|
||||||
{
|
|
||||||
if (type_id == MIE_TYPE_INT) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->ctx_types[type_id]) {
|
|
||||||
return ctx->ctx_types[type_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *type = mie_type_create();
|
|
||||||
if (!type) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
type->t_id = type_id;
|
|
||||||
|
|
||||||
ctx->ctx_types[type_id] = type;
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
return ctx->ctx_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *mie_ctx_get_int_type(struct mie_ctx *ctx, unsigned int nr_bits)
|
|
||||||
{
|
|
||||||
struct ctx_int_cache_entry *entry
|
|
||||||
= get_cached_int_type(&ctx->ctx_int_cache, nr_bits);
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
return &entry->i_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = malloc(sizeof *entry);
|
|
||||||
if (!entry) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(entry, 0x0, sizeof *entry);
|
|
||||||
|
|
||||||
entry->i_type.t_id = MIE_TYPE_INT;
|
|
||||||
entry->i_type.t_width = nr_bits;
|
|
||||||
|
|
||||||
put_cached_int_type(&ctx->ctx_int_cache, entry);
|
|
||||||
return &entry->i_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val)
|
|
||||||
{
|
|
||||||
return MIE_VALUE(val ? ctx->ctx_true : ctx->ctx_false);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_ctx_get_int(
|
|
||||||
struct mie_ctx *ctx, long long val, unsigned int nr_bits)
|
|
||||||
{
|
|
||||||
struct ctx_int_cache_entry *entry
|
|
||||||
= get_cached_int_type(&ctx->ctx_int_cache, nr_bits);
|
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
entry = malloc(sizeof *entry);
|
|
||||||
if (!entry) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(entry, 0x0, sizeof *entry);
|
|
||||||
|
|
||||||
entry->i_type.t_id = MIE_TYPE_INT;
|
|
||||||
entry->i_type.t_width = nr_bits;
|
|
||||||
|
|
||||||
put_cached_int_type(&ctx->ctx_int_cache, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ctx_int_value_cache_entry *value
|
|
||||||
= get_cached_int_value(&entry->i_values, val);
|
|
||||||
if (value) {
|
|
||||||
return MIE_VALUE(&value->i_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
value = malloc(sizeof *value);
|
|
||||||
if (!value) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(value, 0x0, sizeof *value);
|
|
||||||
|
|
||||||
mie_const_init(&value->i_value.i_base, &entry->i_type);
|
|
||||||
value->i_value.i_value = val;
|
|
||||||
|
|
||||||
put_cached_int_value(&entry->i_values, value);
|
|
||||||
|
|
||||||
return MIE_VALUE(&value->i_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel)
|
|
||||||
{
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_data = sel,
|
|
||||||
.key_size = strlen(sel),
|
|
||||||
};
|
|
||||||
|
|
||||||
const b_hashmap_value *cache_entry
|
|
||||||
= b_hashmap_get(ctx->ctx_sel_cache, &key);
|
|
||||||
|
|
||||||
if (cache_entry) {
|
|
||||||
return cache_entry->value_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_selector *sel_value = malloc(sizeof *sel_value);
|
|
||||||
if (!sel_value) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *sel_type = mie_ctx_get_type(ctx, MIE_TYPE_SELECTOR);
|
|
||||||
mie_const_init(&sel_value->sel_base, sel_type);
|
|
||||||
sel_value->sel_value = b_strdup(sel);
|
|
||||||
|
|
||||||
key.key_data = sel_value->sel_value;
|
|
||||||
|
|
||||||
b_hashmap_value hashmap_value = {
|
|
||||||
.value_data = sel_value,
|
|
||||||
.value_size = sizeof *sel_value,
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_put(ctx->ctx_sel_cache, &key, &hashmap_value);
|
|
||||||
|
|
||||||
return MIE_VALUE(sel_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s)
|
|
||||||
{
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_data = s,
|
|
||||||
.key_size = strlen(s),
|
|
||||||
};
|
|
||||||
|
|
||||||
const b_hashmap_value *cache_entry
|
|
||||||
= b_hashmap_get(ctx->ctx_string_cache, &key);
|
|
||||||
|
|
||||||
if (cache_entry) {
|
|
||||||
return cache_entry->value_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_string *string_value = malloc(sizeof *string_value);
|
|
||||||
if (!string_value) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *string_type = mie_ctx_get_type(ctx, MIE_TYPE_STR);
|
|
||||||
mie_const_init(&string_value->s_base, string_type);
|
|
||||||
string_value->s_value = b_strdup(s);
|
|
||||||
|
|
||||||
key.key_data = string_value->s_value;
|
|
||||||
|
|
||||||
b_hashmap_value hashmap_value = {
|
|
||||||
.value_data = string_value,
|
|
||||||
.value_size = sizeof *string_value,
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_put(ctx->ctx_string_cache, &key, &hashmap_value);
|
|
||||||
|
|
||||||
return MIE_VALUE(string_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_ctx_create_array(struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_type *array_type = mie_ctx_get_type(ctx, MIE_TYPE_ARRAY);
|
|
||||||
struct mie_array *array = malloc(sizeof *array);
|
|
||||||
|
|
||||||
if (!array) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(array, 0x0, sizeof *array);
|
|
||||||
mie_const_init(&array->a_base, array_type);
|
|
||||||
|
|
||||||
array->a_values = b_list_create();
|
|
||||||
|
|
||||||
return MIE_VALUE(array);
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef MIE_CTX_H_
|
|
||||||
#define MIE_CTX_H_
|
|
||||||
|
|
||||||
#include <blue/core/btree.h>
|
|
||||||
#include <blue/ds/hashmap.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
struct mie_ctx {
|
|
||||||
struct mie_const *ctx_true, *ctx_false;
|
|
||||||
struct mie_value *ctx_null;
|
|
||||||
struct mie_type *ctx_types[__MIE_TYPE_COUNT];
|
|
||||||
b_btree ctx_int_cache;
|
|
||||||
b_hashmap *ctx_sel_cache;
|
|
||||||
b_hashmap *ctx_string_cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_ctx *mie_ctx_create(void);
|
|
||||||
extern void mie_ctx_destroy(struct mie_ctx *ctx);
|
|
||||||
|
|
||||||
extern struct mie_type *mie_ctx_get_type(
|
|
||||||
struct mie_ctx *ctx, enum mie_type_id type_id);
|
|
||||||
extern struct mie_type *mie_ctx_get_int_type(
|
|
||||||
struct mie_ctx *ctx, unsigned int nr_bits);
|
|
||||||
extern struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx);
|
|
||||||
extern struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val);
|
|
||||||
extern struct mie_value *mie_ctx_get_int(
|
|
||||||
struct mie_ctx *ctx, long long val, unsigned int nr_bits);
|
|
||||||
extern struct mie_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s);
|
|
||||||
extern struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel);
|
|
||||||
extern struct mie_value *mie_ctx_create_array(struct mie_ctx *ctx);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#ifndef MIE_ALLOCA_H_
|
|
||||||
#define MIE_ALLOCA_H_
|
|
||||||
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
struct mie_alloca {
|
|
||||||
struct mie_instr a_base;
|
|
||||||
struct mie_type *a_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#ifndef MIE_ARG_H_
|
|
||||||
#define MIE_ARG_H_
|
|
||||||
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
#define MIE_ARG(p) ((struct mie_arg *)(p))
|
|
||||||
|
|
||||||
struct mie_arg {
|
|
||||||
struct mie_value arg_base;
|
|
||||||
struct mie_type *arg_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_arg *mie_arg_create(struct mie_type *type);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#ifndef MIE_BLOCK_H_
|
|
||||||
#define MIE_BLOCK_H_
|
|
||||||
|
|
||||||
#define MIE_BLOCK(p) ((struct mie_block *)(p))
|
|
||||||
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
struct mie_block {
|
|
||||||
struct mie_value b_base;
|
|
||||||
struct mie_func *b_parent;
|
|
||||||
/* the phi instruction(s). these must appear at the start of the block
|
|
||||||
* and are separated to make traversing the CFG easier */
|
|
||||||
b_queue b_phi;
|
|
||||||
/* the rest of the instructions in the block */
|
|
||||||
b_queue b_instr;
|
|
||||||
/* the instruction that transfers control to the next block,
|
|
||||||
* could be a switch, branch, or ret */
|
|
||||||
struct mie_instr *b_terminator;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API struct mie_block *mie_block_create(
|
|
||||||
struct mie_func *parent, const char *name);
|
|
||||||
MIE_API bool mie_block_add_instr(struct mie_block *block, struct mie_instr *instr);
|
|
||||||
|
|
||||||
static inline bool mie_block_is_terminated(const struct mie_block *block)
|
|
||||||
{
|
|
||||||
return block->b_terminator != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#ifndef MIE_BRANCH_H_
|
|
||||||
#define MIE_BRANCH_H_
|
|
||||||
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
|
|
||||||
struct mie_branch {
|
|
||||||
struct mie_instr b_base;
|
|
||||||
struct mie_block *b_dest;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_branch_if {
|
|
||||||
struct mie_instr b_base;
|
|
||||||
struct mie_value *b_cond;
|
|
||||||
struct mie_block *b_true_block;
|
|
||||||
struct mie_block *b_false_block;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#ifndef MIE_BUILDER_H_
|
|
||||||
#define MIE_BUILDER_H_
|
|
||||||
|
|
||||||
#include <blue/core/btree.h>
|
|
||||||
#include <mie/ir/switch.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
struct b_hashmap;
|
|
||||||
|
|
||||||
struct mie_block;
|
|
||||||
struct mie_module;
|
|
||||||
struct mie_data;
|
|
||||||
struct mie_type;
|
|
||||||
struct mie_phi;
|
|
||||||
struct mie_phi_edge;
|
|
||||||
struct mie_ctx;
|
|
||||||
|
|
||||||
struct mie_builder {
|
|
||||||
struct mie_ctx *b_ctx;
|
|
||||||
struct mie_module *b_module;
|
|
||||||
struct mie_block *b_current_block;
|
|
||||||
struct mie_instr *b_prev_instr;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mie_builder_flags {
|
|
||||||
MIE_BUILDER_IGNORE_RESULT = 0x01u,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_builder *mie_builder_create(
|
|
||||||
struct mie_ctx *ctx, struct mie_module *mod);
|
|
||||||
extern void mie_builder_destroy(struct mie_builder *builder);
|
|
||||||
|
|
||||||
extern struct mie_func *mie_builder_get_current_func(struct mie_builder *builder);
|
|
||||||
static inline struct mie_block *mie_builder_get_current_block(
|
|
||||||
struct mie_builder *builder)
|
|
||||||
{
|
|
||||||
return builder->b_current_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern struct mie_record *mie_builder_put_record(
|
|
||||||
struct mie_builder *builder, struct mie_const *val, const char *name);
|
|
||||||
extern struct mie_record *mie_builder_get_record(
|
|
||||||
struct mie_builder *builder, const char *name);
|
|
||||||
extern void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data);
|
|
||||||
extern void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type);
|
|
||||||
extern void mie_builder_set_insert_point(
|
|
||||||
struct mie_builder *builder, struct mie_block *block);
|
|
||||||
|
|
||||||
extern struct mie_value *mie_builder_get_data_ptr(
|
|
||||||
struct mie_builder *builder, const char *data_ident);
|
|
||||||
extern struct mie_value *mie_builder_get_string_ptr(
|
|
||||||
struct mie_builder *builder, const char *s);
|
|
||||||
|
|
||||||
extern struct mie_value *mie_builder_ret(
|
|
||||||
struct mie_builder *builder, struct mie_value *val);
|
|
||||||
extern struct mie_value *mie_builder_add(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_sub(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_mul(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_div(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_load(
|
|
||||||
struct mie_builder *builder, struct mie_type *type,
|
|
||||||
struct mie_value *src, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_store(
|
|
||||||
struct mie_builder *builder, struct mie_value *val, struct mie_value *dest);
|
|
||||||
extern struct mie_value *mie_builder_alloca(
|
|
||||||
struct mie_builder *builder, struct mie_type *type, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_switch(
|
|
||||||
struct mie_builder *builder, struct mie_value *cond,
|
|
||||||
struct mie_switch_branch *branches, size_t nr_branches,
|
|
||||||
struct mie_block *default_block);
|
|
||||||
extern struct mie_value *mie_builder_br(
|
|
||||||
struct mie_builder *builder, struct mie_block *dest);
|
|
||||||
extern struct mie_value *mie_builder_br_if(
|
|
||||||
struct mie_builder *builder, struct mie_value *cond,
|
|
||||||
struct mie_block *if_true, struct mie_block *if_false);
|
|
||||||
extern struct mie_value *mie_builder_msg(
|
|
||||||
struct mie_builder *builder, struct mie_type *ret_type,
|
|
||||||
struct mie_value *recipient, struct mie_value *selector,
|
|
||||||
struct mie_value **args, size_t nr_args, enum mie_builder_flags flags,
|
|
||||||
const char *name);
|
|
||||||
extern struct mie_value *mie_builder_cmp_eq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_cmp_neq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_cmp_lt(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_cmp_gt(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_cmp_leq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_cmp_geq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_getelementptr(
|
|
||||||
struct mie_builder *builder, struct mie_type *container_type,
|
|
||||||
struct mie_value *container, struct mie_value *index, const char *name);
|
|
||||||
extern struct mie_value *mie_builder_setelementptr(
|
|
||||||
struct mie_builder *builder, struct mie_type *container_type,
|
|
||||||
struct mie_value *container, struct mie_value *index);
|
|
||||||
extern struct mie_value *mie_builder_phi(
|
|
||||||
struct mie_builder *builder, struct mie_type *type,
|
|
||||||
struct mie_phi_edge *edges, unsigned int nr_edges, const char *name);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
#ifndef MIE_CONST_H_
|
|
||||||
#define MIE_CONST_H_
|
|
||||||
|
|
||||||
#include <blue/ds/list.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
#define MIE_CONST(p) ((struct mie_const *)(p))
|
|
||||||
|
|
||||||
#define MIE_INT(p) ((struct mie_int *)(p))
|
|
||||||
#define MIE_DOUBLE(p) ((struct mie_double *)(p))
|
|
||||||
#define MIE_STRING(p) ((struct mie_string *)(p))
|
|
||||||
#define MIE_ATOM(p) ((struct mie_atom *)(p))
|
|
||||||
#define MIE_SELECTOR(p) ((struct mie_selector *)(p))
|
|
||||||
#define MIE_ARRAY(p) ((struct mie_array *)(p))
|
|
||||||
|
|
||||||
struct mie_const {
|
|
||||||
struct mie_value c_base;
|
|
||||||
struct mie_type *c_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_int {
|
|
||||||
struct mie_const i_base;
|
|
||||||
int64_t i_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_double {
|
|
||||||
struct mie_const d_base;
|
|
||||||
double d_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_string {
|
|
||||||
struct mie_const s_base;
|
|
||||||
char *s_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_atom {
|
|
||||||
struct mie_const a_base;
|
|
||||||
char *a_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_selector {
|
|
||||||
struct mie_const sel_base;
|
|
||||||
char *sel_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_array {
|
|
||||||
struct mie_const a_base;
|
|
||||||
b_list *a_values;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void mie_const_init(struct mie_const *c, struct mie_type *type);
|
|
||||||
|
|
||||||
static inline bool mie_value_is_selector(const struct mie_value *v)
|
|
||||||
{
|
|
||||||
if (v->v_type->t_id != MIE_VALUE_CONST) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_const *c = MIE_CONST(v);
|
|
||||||
|
|
||||||
return c->c_type->t_id == MIE_TYPE_SELECTOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
#ifndef MIE_CONVERT_H_
|
|
||||||
#define MIE_CONVERT_H_
|
|
||||||
|
|
||||||
#include <blue/core/stringstream.h>
|
|
||||||
#include <blue/ds/bitbuffer.h>
|
|
||||||
#include <blue/ds/string.h>
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
struct mie_value;
|
|
||||||
struct mie_ctx;
|
|
||||||
|
|
||||||
enum mie_ir_format {
|
|
||||||
MIE_IR_NONE = 0,
|
|
||||||
MIE_IR_MEM,
|
|
||||||
MIE_IR_BITCODE,
|
|
||||||
MIE_IR_TEXT,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mie_ir_converter_medium {
|
|
||||||
MIE_IR_CONVERTER_NONE = 0,
|
|
||||||
MIE_IR_CONVERTER_MIE_VALUE,
|
|
||||||
MIE_IR_CONVERTER_BITSTREAM,
|
|
||||||
MIE_IR_CONVERTER_BITBUFFER,
|
|
||||||
MIE_IR_CONVERTER_STRINGSTREAM,
|
|
||||||
MIE_IR_CONVERTER_STRING,
|
|
||||||
MIE_IR_CONVERTER_FILE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_ir_converter {
|
|
||||||
struct mie_ctx *c_ctx;
|
|
||||||
enum mie_ir_format c_src_format, c_dest_format;
|
|
||||||
enum mie_ir_converter_medium c_src_medium, c_dest_medium;
|
|
||||||
|
|
||||||
union {
|
|
||||||
/* TODO bitstream */
|
|
||||||
struct mie_value *value;
|
|
||||||
b_bitbuffer *bitbuffer;
|
|
||||||
b_stringstream *stringstream;
|
|
||||||
b_string *string;
|
|
||||||
FILE *file;
|
|
||||||
} c_src;
|
|
||||||
|
|
||||||
union {
|
|
||||||
/* TODO bitstream */
|
|
||||||
struct mie_value **value;
|
|
||||||
b_bitbuffer *bitbuffer;
|
|
||||||
b_stringstream *stringstream;
|
|
||||||
b_string *string;
|
|
||||||
FILE *file;
|
|
||||||
} c_dest;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API struct mie_ir_converter *mie_ir_converter_create(
|
|
||||||
struct mie_ctx *ctx, enum mie_ir_format src, enum mie_ir_format dest);
|
|
||||||
MIE_API void mie_ir_converter_destroy(struct mie_ir_converter *converter);
|
|
||||||
|
|
||||||
MIE_API b_status mie_ir_converter_set_src_value(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value);
|
|
||||||
MIE_API b_status mie_ir_converter_set_src_bitbuffer(
|
|
||||||
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer);
|
|
||||||
MIE_API b_status mie_ir_converter_set_src_stringstream(
|
|
||||||
struct mie_ir_converter *converter, b_stringstream *stringstream);
|
|
||||||
MIE_API b_status mie_ir_converter_set_src_string(
|
|
||||||
struct mie_ir_converter *converter, b_string *string);
|
|
||||||
MIE_API b_status mie_ir_converter_set_src_file(
|
|
||||||
struct mie_ir_converter *converter, FILE *file);
|
|
||||||
|
|
||||||
MIE_API b_status mie_ir_converter_set_dest_value(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **value);
|
|
||||||
MIE_API b_status mie_ir_converter_set_dest_bitbuffer(
|
|
||||||
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer);
|
|
||||||
MIE_API b_status mie_ir_converter_set_dest_stringstream(
|
|
||||||
struct mie_ir_converter *converter, b_stringstream *stringstream);
|
|
||||||
MIE_API b_status mie_ir_converter_set_dest_string(
|
|
||||||
struct mie_ir_converter *converter, b_string *string);
|
|
||||||
MIE_API b_status mie_ir_converter_set_dest_file(
|
|
||||||
struct mie_ir_converter *converter, FILE *file);
|
|
||||||
|
|
||||||
MIE_API b_status mie_ir_converter_process(struct mie_ir_converter *converter);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef MIE_DATA_H_
|
|
||||||
#define MIE_DATA_H_
|
|
||||||
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
#define MIE_DATA(p) ((struct mie_data *)(p))
|
|
||||||
|
|
||||||
enum mie_data_type {
|
|
||||||
MIE_DATA_NONE = 0,
|
|
||||||
MIE_DATA_EXTERN_GLOBAL,
|
|
||||||
MIE_DATA_CONST,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_data {
|
|
||||||
struct mie_value d_base;
|
|
||||||
enum mie_data_type d_type;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
struct mie_const *c_value;
|
|
||||||
} d_const;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct mie_type *g_type;
|
|
||||||
} d_extern_global;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_data *mie_data_create_extern_global(
|
|
||||||
struct mie_type *type, const char *ident);
|
|
||||||
extern struct mie_data *mie_data_create_const(struct mie_const *value);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#ifndef MIE_FUNC_H_
|
|
||||||
#define MIE_FUNC_H_
|
|
||||||
|
|
||||||
#define MIE_FUNC(p) ((struct mie_func *)(p))
|
|
||||||
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
struct mie_name_map;
|
|
||||||
struct mie_type;
|
|
||||||
struct mie_arg;
|
|
||||||
struct mie_block;
|
|
||||||
struct b_dict;
|
|
||||||
|
|
||||||
enum mie_func_type {
|
|
||||||
MIE_FUNC_NONE = 0x00u,
|
|
||||||
MIE_FUNC_STATIC = 0x01u,
|
|
||||||
MIE_FUNC_INSTANCE = 0x02u,
|
|
||||||
MIE_FUNC_LAMBDA = 0x03u,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_func {
|
|
||||||
struct mie_value f_base;
|
|
||||||
|
|
||||||
enum mie_func_type f_type;
|
|
||||||
struct mie_type *f_ret;
|
|
||||||
|
|
||||||
struct mie_name_map *f_names;
|
|
||||||
|
|
||||||
b_queue f_args;
|
|
||||||
b_queue f_blocks;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_func *mie_func_create(
|
|
||||||
enum mie_func_type type, struct mie_type *ret_type);
|
|
||||||
extern struct mie_value *mie_func_add_arg(
|
|
||||||
struct mie_func *func, struct mie_type *type, const char *name);
|
|
||||||
extern struct mie_block *mie_func_create_block(
|
|
||||||
struct mie_func *func, const char *name);
|
|
||||||
extern void mie_func_insert_block(
|
|
||||||
struct mie_func *func, struct mie_block *block, struct mie_block *after);
|
|
||||||
extern struct mie_value *mie_func_generate_value_name(
|
|
||||||
struct mie_func *func, struct mie_value *val, const char *hint);
|
|
||||||
|
|
||||||
extern struct mie_block *mie_func_get_first_block(struct mie_func *func);
|
|
||||||
extern struct mie_block *mie_func_get_last_block(struct mie_func *func);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#ifndef MIE_INSTR_H_
|
|
||||||
#define MIE_INSTR_H_
|
|
||||||
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
#define MIE_INSTR(p) ((struct mie_instr *)(p))
|
|
||||||
|
|
||||||
enum mie_instr_type {
|
|
||||||
MIE_INSTR_NONE = 0,
|
|
||||||
MIE_INSTR_RET,
|
|
||||||
MIE_INSTR_ADD,
|
|
||||||
MIE_INSTR_SUB,
|
|
||||||
MIE_INSTR_MUL,
|
|
||||||
MIE_INSTR_DIV,
|
|
||||||
MIE_INSTR_LOAD,
|
|
||||||
MIE_INSTR_STORE,
|
|
||||||
MIE_INSTR_ALLOCA,
|
|
||||||
MIE_INSTR_SWITCH,
|
|
||||||
MIE_INSTR_BR,
|
|
||||||
MIE_INSTR_BR_IF,
|
|
||||||
MIE_INSTR_MSG,
|
|
||||||
MIE_INSTR_CMP_EQ,
|
|
||||||
MIE_INSTR_CMP_NEQ,
|
|
||||||
MIE_INSTR_CMP_LT,
|
|
||||||
MIE_INSTR_CMP_GT,
|
|
||||||
MIE_INSTR_CMP_LEQ,
|
|
||||||
MIE_INSTR_CMP_GEQ,
|
|
||||||
MIE_INSTR_GETELEMENTPTR,
|
|
||||||
MIE_INSTR_SETELEMENTPTR,
|
|
||||||
MIE_INSTR_PHI,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_instr {
|
|
||||||
struct mie_value i_base;
|
|
||||||
enum mie_instr_type i_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_ret {
|
|
||||||
struct mie_instr r_base;
|
|
||||||
struct mie_value *r_val;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void mie_instr_init(struct mie_instr *instr, enum mie_instr_type type);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#ifndef MIE_MODULE_H_
|
|
||||||
#define MIE_MODULE_H_
|
|
||||||
|
|
||||||
#define MIE_MODULE(p) ((struct mie_module *)(p))
|
|
||||||
|
|
||||||
#include <blue/core/queue.h>
|
|
||||||
#include <blue/ds/hashmap.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <mie/name.h>
|
|
||||||
|
|
||||||
struct mie_func;
|
|
||||||
|
|
||||||
struct mie_module {
|
|
||||||
struct mie_value m_base;
|
|
||||||
struct mie_name_map *m_names;
|
|
||||||
b_queue m_records;
|
|
||||||
b_queue m_types;
|
|
||||||
b_queue m_func;
|
|
||||||
|
|
||||||
b_hashmap *m_data;
|
|
||||||
b_hashmap *m_data_strings;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_module *mie_module_create(void);
|
|
||||||
extern void mie_module_add_function(
|
|
||||||
struct mie_module *mod, struct mie_func *func, const char *name);
|
|
||||||
extern struct mie_data *mie_module_get_string_ptr(
|
|
||||||
struct mie_module *mod, const char *s);
|
|
||||||
extern struct mie_data *mie_module_get_data(
|
|
||||||
struct mie_module *mod, const char *name);
|
|
||||||
extern enum b_status mie_module_put_data(
|
|
||||||
struct mie_module *mod, struct mie_data *data, const char *name);
|
|
||||||
|
|
||||||
extern struct mie_value *mie_module_generate_value_name(
|
|
||||||
struct mie_module *mod, struct mie_value *val, const char *hint);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#ifndef MIE_MSG_H_
|
|
||||||
#define MIE_MSG_H_
|
|
||||||
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
#define MIE_MSG(p) ((struct mie_msg *)(p))
|
|
||||||
|
|
||||||
struct mie_msg {
|
|
||||||
struct mie_instr msg_base;
|
|
||||||
struct mie_type *msg_ret_type;
|
|
||||||
struct mie_value *msg_recipient;
|
|
||||||
struct mie_value *msg_selector;
|
|
||||||
size_t msg_nr_args;
|
|
||||||
struct mie_value **msg_args;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#ifndef MIE_ARITH_H_
|
|
||||||
#define MIE_ARITH_H_
|
|
||||||
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
|
|
||||||
struct mie_binary_op {
|
|
||||||
struct mie_instr op_base;
|
|
||||||
struct mie_type *op_type;
|
|
||||||
struct mie_value *op_left;
|
|
||||||
struct mie_value *op_right;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#ifndef MIE_PHI_H_
|
|
||||||
#define MIE_PHI_H_
|
|
||||||
|
|
||||||
#include <blue/core/queue.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/misc.h>
|
|
||||||
|
|
||||||
struct mie_phi_edge {
|
|
||||||
b_queue_entry e_entry;
|
|
||||||
struct mie_block *e_incoming_block;
|
|
||||||
struct mie_value *e_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_phi {
|
|
||||||
struct mie_instr p_base;
|
|
||||||
struct mie_type *p_type;
|
|
||||||
|
|
||||||
unsigned int p_nr_edges;
|
|
||||||
struct mie_phi_edge *p_edges;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API struct mie_phi_edge *mie_phi_edge_create(
|
|
||||||
struct mie_block *incoming_block, struct mie_value *value);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#ifndef MIE_PTR_H_
|
|
||||||
#define MIE_PTR_H_
|
|
||||||
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
struct mie_getelementptr {
|
|
||||||
struct mie_instr gep_base;
|
|
||||||
struct mie_type *gep_container_type;
|
|
||||||
struct mie_value *gep_container;
|
|
||||||
struct mie_value *gep_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_setelementptr {
|
|
||||||
struct mie_instr sep_base;
|
|
||||||
struct mie_type *sep_container_type;
|
|
||||||
struct mie_value *sep_container;
|
|
||||||
struct mie_value *sep_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_load {
|
|
||||||
struct mie_instr l_base;
|
|
||||||
struct mie_type *l_type;
|
|
||||||
struct mie_value *l_src;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_store {
|
|
||||||
struct mie_instr s_base;
|
|
||||||
struct mie_value *s_val;
|
|
||||||
struct mie_value *s_dest;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#ifndef MIE_RECORD_H_
|
|
||||||
#define MIE_RECORD_H_
|
|
||||||
|
|
||||||
#define MIE_RECORD(p) ((struct mie_record *)(p))
|
|
||||||
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
struct mie_record {
|
|
||||||
struct mie_value r_base;
|
|
||||||
const struct mie_const *r_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_record *mie_record_create(const struct mie_const *val);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef MIE_SWITCH_H_
|
|
||||||
#define MIE_SWITCH_H_
|
|
||||||
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
|
|
||||||
struct mie_switch_branch {
|
|
||||||
struct mie_value *b_value;
|
|
||||||
struct mie_block *b_jump_to;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_switch {
|
|
||||||
struct mie_instr s_base;
|
|
||||||
struct mie_value *s_src;
|
|
||||||
struct mie_block *s_default;
|
|
||||||
|
|
||||||
size_t s_nr_branches;
|
|
||||||
struct mie_switch_branch *s_branches;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#ifndef MIE_VALUE_H_
|
|
||||||
#define MIE_VALUE_H_
|
|
||||||
|
|
||||||
#include <blue/core/queue.h>
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <mie/name.h>
|
|
||||||
|
|
||||||
#define MIE_VALUE(p) ((struct mie_value *)(p))
|
|
||||||
|
|
||||||
struct mie_ctx;
|
|
||||||
struct mie_value;
|
|
||||||
|
|
||||||
enum mie_value_type_id {
|
|
||||||
MIE_VALUE_NONE = 0,
|
|
||||||
MIE_VALUE_MODULE,
|
|
||||||
MIE_VALUE_TYPE,
|
|
||||||
MIE_VALUE_RECORD,
|
|
||||||
MIE_VALUE_FUNC,
|
|
||||||
MIE_VALUE_ARG,
|
|
||||||
MIE_VALUE_BLOCK,
|
|
||||||
MIE_VALUE_INSTR,
|
|
||||||
MIE_VALUE_CONST,
|
|
||||||
MIE_VALUE_DATA,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mie_value_flags {
|
|
||||||
MIE_VALUE_F_NONE = 0x00u,
|
|
||||||
MIE_VALUE_F_STATIC = 0x01u,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_value_type {
|
|
||||||
enum mie_value_type_id t_id;
|
|
||||||
struct mie_type *(*t_get_type)(struct mie_value *, struct mie_ctx *);
|
|
||||||
void (*t_cleanup)(struct mie_value *);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_value {
|
|
||||||
struct mie_name v_name;
|
|
||||||
const struct mie_value_type *v_type;
|
|
||||||
enum mie_value_flags v_flags;
|
|
||||||
b_queue_entry v_entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API void mie_value_init(struct mie_value *val, enum mie_value_type_id type);
|
|
||||||
MIE_API void mie_value_destroy(struct mie_value *val);
|
|
||||||
|
|
||||||
MIE_API struct mie_type *mie_value_get_type(
|
|
||||||
struct mie_value *val, struct mie_ctx *ctx);
|
|
||||||
|
|
||||||
static inline bool mie_value_is(
|
|
||||||
const struct mie_value *val, enum mie_value_type_id type_id)
|
|
||||||
{
|
|
||||||
if (!val->v_type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val->v_type->t_id == type_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef MIE_MISC_H_
|
|
||||||
#define MIE_MISC_H_
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && MIE_STATIC == 0
|
|
||||||
#ifdef MIE_EXPORT
|
|
||||||
#define MIE_API extern __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define MIE_API extern __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define MIE_API extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
||||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef MIE_NAME_H_
|
|
||||||
#define MIE_NAME_H_
|
|
||||||
|
|
||||||
#include <blue/core/btree.h>
|
|
||||||
#include <blue/core/queue.h>
|
|
||||||
|
|
||||||
#define MIE_NAME_VALID(p) (((p)->n_str) != NULL)
|
|
||||||
|
|
||||||
struct mie_name_map;
|
|
||||||
|
|
||||||
enum mie_name_map_flags {
|
|
||||||
MIE_NAME_MAP_STRICT = 0x01u,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mie_name_map_entry_type {
|
|
||||||
MIE_NAME_MAP_E_NONE = 0,
|
|
||||||
MIE_NAME_MAP_E_NAME,
|
|
||||||
MIE_NAME_MAP_E_BUCKET,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_name_map_entry {
|
|
||||||
enum mie_name_map_entry_type e_type;
|
|
||||||
uint64_t e_hash;
|
|
||||||
union {
|
|
||||||
b_queue_entry e_entry;
|
|
||||||
b_btree_node e_node;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_name {
|
|
||||||
struct mie_name_map_entry n_base;
|
|
||||||
struct mie_name_map *n_parent;
|
|
||||||
char *n_str;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_name_bucket {
|
|
||||||
struct mie_name_map_entry b_base;
|
|
||||||
b_queue b_names;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_name_map {
|
|
||||||
b_btree m_entries;
|
|
||||||
size_t m_next_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_name_map *mie_name_map_create(void);
|
|
||||||
extern void mie_name_map_destroy(struct mie_name_map *map);
|
|
||||||
|
|
||||||
extern struct mie_name *mie_name_map_put(
|
|
||||||
struct mie_name_map *map, struct mie_name *entry, const char *hint,
|
|
||||||
enum mie_name_map_flags flags);
|
|
||||||
|
|
||||||
extern void mie_name_destroy(struct mie_name *name);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef MIE_SELECT_BUILDER_H_
|
|
||||||
#define MIE_SELECT_BUILDER_H_
|
|
||||||
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <mie/status.h>
|
|
||||||
|
|
||||||
struct mie_ctx;
|
|
||||||
struct mie_instr;
|
|
||||||
struct mie_value;
|
|
||||||
struct mie_select_builder;
|
|
||||||
struct mie_select_node;
|
|
||||||
struct mie_select_graph;
|
|
||||||
struct mie_select_value;
|
|
||||||
struct mie_target;
|
|
||||||
|
|
||||||
MIE_API struct mie_select_builder *mie_select_builder_create(
|
|
||||||
struct mie_ctx *ctx, const struct mie_target *target);
|
|
||||||
MIE_API void mie_select_builder_destroy(struct mie_select_builder *builder);
|
|
||||||
|
|
||||||
MIE_API struct mie_select_graph *mie_select_builder_get_graph(
|
|
||||||
struct mie_select_builder *builder);
|
|
||||||
MIE_API struct mie_ctx *mie_select_builder_get_ctx(
|
|
||||||
struct mie_select_builder *builder);
|
|
||||||
MIE_API const struct mie_target *mie_select_builder_get_target(
|
|
||||||
struct mie_select_builder *builder);
|
|
||||||
MIE_API struct mie_select_graph *mie_select_builder_finish(
|
|
||||||
struct mie_select_builder *builder);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_builder_get_const(
|
|
||||||
struct mie_select_builder *builder, long long value,
|
|
||||||
struct mie_select_value *out);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_builder_push_instr(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr);
|
|
||||||
|
|
||||||
MIE_API struct mie_select_node *mie_select_builder_find_node_with_ivalue(
|
|
||||||
struct mie_select_builder *builder, const struct mie_target *target,
|
|
||||||
unsigned int opcode, long long val);
|
|
||||||
|
|
||||||
MIE_API struct mie_select_value *mie_select_builder_get_value(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val);
|
|
||||||
MIE_API enum mie_status mie_select_builder_set_value(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *graph_val);
|
|
||||||
|
|
||||||
MIE_API struct mie_select_value *mie_select_builder_get_mem_access(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val);
|
|
||||||
MIE_API enum mie_status mie_select_builder_set_mem_access(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *graph_val);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_builder_collapse_chain_ends(
|
|
||||||
struct mie_select_builder *builder, struct mie_select_value *out);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#ifndef MIE_SELECT_GRAPH_H_
|
|
||||||
#define MIE_SELECT_GRAPH_H_
|
|
||||||
|
|
||||||
#include <blue/core/btree.h>
|
|
||||||
#include <blue/core/queue.h>
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <mie/target/target.h>
|
|
||||||
|
|
||||||
struct mie_ctx;
|
|
||||||
struct mie_type;
|
|
||||||
struct mie_instr;
|
|
||||||
|
|
||||||
struct mie_select_value {
|
|
||||||
struct mie_select_node *v_node;
|
|
||||||
unsigned int v_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_use {
|
|
||||||
struct mie_select_node *u_user;
|
|
||||||
struct mie_select_value u_value;
|
|
||||||
b_queue_entry u_entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_chain_end {
|
|
||||||
struct mie_select_value c_value;
|
|
||||||
b_queue_entry c_entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_graph {
|
|
||||||
b_queue g_nodes;
|
|
||||||
struct mie_select_node *g_root;
|
|
||||||
struct mie_select_value g_entry;
|
|
||||||
b_queue g_chain_ends;
|
|
||||||
size_t g_frame_index;
|
|
||||||
size_t g_node_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_use_iterator {
|
|
||||||
b_queue_entry *it_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API struct mie_select_graph *mie_select_graph_create(struct mie_ctx *ctx);
|
|
||||||
MIE_API void mie_select_graph_destroy(struct mie_select_graph *graph);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_graph_get_node(
|
|
||||||
struct mie_select_graph *graph, const struct mie_target *target,
|
|
||||||
unsigned int op, struct mie_select_value **operands, size_t nr_operands,
|
|
||||||
struct mie_type **values, size_t nr_values, struct mie_select_node **out);
|
|
||||||
|
|
||||||
MIE_API void mie_select_graph_dump_text(struct mie_select_graph *graph);
|
|
||||||
MIE_API void mie_select_graph_dump_dot(
|
|
||||||
struct mie_select_graph *graph, const char *filename);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
#ifndef MIE_SELECT_NODE_H_
|
|
||||||
#define MIE_SELECT_NODE_H_
|
|
||||||
|
|
||||||
#include <blue/core/queue.h>
|
|
||||||
#include <mie/status.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
|
|
||||||
#define MIE_SELECT_NODE_OUTPUT_MAX 4
|
|
||||||
|
|
||||||
struct mie_target;
|
|
||||||
struct mie_value;
|
|
||||||
struct mie_select_value;
|
|
||||||
|
|
||||||
enum mie_select_node_flags {
|
|
||||||
MIE_SELECT_NODE_F_IVALUE = 0x01u,
|
|
||||||
MIE_SELECT_NODE_F_PVALUE = 0x02u,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_node {
|
|
||||||
size_t n_id;
|
|
||||||
unsigned long n_opcode;
|
|
||||||
enum mie_select_node_flags n_flags;
|
|
||||||
|
|
||||||
char *n_description;
|
|
||||||
|
|
||||||
/* certain "builtin" parameters that can be used by opcodes */
|
|
||||||
struct {
|
|
||||||
struct mie_value *v;
|
|
||||||
long long i;
|
|
||||||
void *p;
|
|
||||||
} n_value;
|
|
||||||
|
|
||||||
/* queue entry, links to mie_select_graph.g_nodes */
|
|
||||||
b_queue_entry n_entry;
|
|
||||||
|
|
||||||
/* linked lists of struct mie_select_use,
|
|
||||||
* listing all the places where this node is being used as an
|
|
||||||
* operand.
|
|
||||||
* these pointers point to data in another node's n_operands,
|
|
||||||
* and the memory belongs to these other nodes, not us.
|
|
||||||
*/
|
|
||||||
b_queue n_use;
|
|
||||||
|
|
||||||
/* array of struct mie_select_use
|
|
||||||
* listing all the nodes that are being used as operands by
|
|
||||||
* this node. other nodes hold pointers to these mie_select_use array
|
|
||||||
* entries as part of their n_use queue.
|
|
||||||
*/
|
|
||||||
struct mie_select_use *n_operands;
|
|
||||||
size_t n_nr_operands;
|
|
||||||
|
|
||||||
/* array of struct mie_type pointers
|
|
||||||
* listing the types of the values that are produced as outputs by
|
|
||||||
* this node. the type pointers themselves are owned by a mie_ctx.
|
|
||||||
*/
|
|
||||||
struct mie_type **n_results;
|
|
||||||
size_t n_nr_results;
|
|
||||||
|
|
||||||
/* the target system that provides the operation described by n_opcode. */
|
|
||||||
const struct mie_target *n_target;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_node_iterator {
|
|
||||||
b_queue_entry *it_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline struct mie_select_node *mie_select_node_iterator_unbox(
|
|
||||||
struct mie_select_node_iterator *it)
|
|
||||||
{
|
|
||||||
return b_unbox(struct mie_select_node, it->it_ptr, n_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
MIE_API void mie_select_node_iterator_next(struct mie_select_node_iterator *it);
|
|
||||||
MIE_API bool mie_select_node_iterator_is_valid(
|
|
||||||
const struct mie_select_node_iterator *it);
|
|
||||||
|
|
||||||
MIE_API struct mie_select_node *mie_select_node_create(
|
|
||||||
const struct mie_target *target, unsigned int op,
|
|
||||||
struct mie_type **results, size_t nr_results);
|
|
||||||
MIE_API void mie_select_node_destroy(struct mie_select_node *node);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_node_set_operands(
|
|
||||||
struct mie_select_node *node, struct mie_select_value *operands,
|
|
||||||
size_t nr_operands);
|
|
||||||
MIE_API enum mie_status mie_select_node_clear_operands(struct mie_select_node *node);
|
|
||||||
|
|
||||||
MIE_API void mie_select_node_get_users(
|
|
||||||
struct mie_select_node *node, struct mie_select_node_iterator *it);
|
|
||||||
MIE_API void mie_select_node_get_uses(
|
|
||||||
struct mie_select_node *node, struct mie_select_node_iterator *it);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_node_get_value(
|
|
||||||
struct mie_select_node *node, struct mie_type *type, size_t index,
|
|
||||||
struct mie_select_value *out);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_select_node_set_description(
|
|
||||||
struct mie_select_node *node, const char *format, ...);
|
|
||||||
|
|
||||||
MIE_API struct mie_select_node *mie_select_node_get_glued_node(
|
|
||||||
struct mie_select_node *node);
|
|
||||||
MIE_API struct mie_select_node *mie_select_node_get_glued_user(
|
|
||||||
struct mie_select_node *node);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#ifndef MIE_SELECT_OPCODE_H_
|
|
||||||
#define MIE_SELECT_OPCODE_H_
|
|
||||||
|
|
||||||
enum mie_select_opcode {
|
|
||||||
MIE_SELECT_OP_NONE = 0,
|
|
||||||
MIE_SELECT_OP_ENTRY,
|
|
||||||
MIE_SELECT_OP_ROOT,
|
|
||||||
MIE_SELECT_OP_BLOCK,
|
|
||||||
MIE_SELECT_OP_CONSTANT,
|
|
||||||
MIE_SELECT_OP_FRAME_INDEX,
|
|
||||||
MIE_SELECT_OP_REGISTER,
|
|
||||||
MIE_SELECT_OP_COPY_FROM_REG,
|
|
||||||
MIE_SELECT_OP_COPY_TO_REG,
|
|
||||||
MIE_SELECT_OP_GLOBAL_ADDRESS,
|
|
||||||
MIE_SELECT_OP_CHAIN_GROUP,
|
|
||||||
MIE_SELECT_OP_LOAD,
|
|
||||||
MIE_SELECT_OP_STORE,
|
|
||||||
MIE_SELECT_OP_ADD,
|
|
||||||
MIE_SELECT_OP_SUB,
|
|
||||||
MIE_SELECT_OP_MUL,
|
|
||||||
MIE_SELECT_OP_DIV,
|
|
||||||
MIE_SELECT_OP_XOR,
|
|
||||||
MIE_SELECT_OP_CMP_EQ,
|
|
||||||
MIE_SELECT_OP_CMP_NEQ,
|
|
||||||
MIE_SELECT_OP_CMP_LT,
|
|
||||||
MIE_SELECT_OP_CMP_GT,
|
|
||||||
MIE_SELECT_OP_CMP_LEQ,
|
|
||||||
MIE_SELECT_OP_CMP_GEQ,
|
|
||||||
MIE_SELECT_OP_BR,
|
|
||||||
MIE_SELECT_OP_BR_COND,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef MIE_STATUS_H_
|
|
||||||
#define MIE_STATUS_H_
|
|
||||||
|
|
||||||
#include <mie/misc.h>
|
|
||||||
|
|
||||||
#define MIE_ERROR_VENDOR (ivy_error_vendor())
|
|
||||||
|
|
||||||
struct b_error_vendor;
|
|
||||||
|
|
||||||
enum mie_status {
|
|
||||||
MIE_SUCCESS = 0,
|
|
||||||
MIE_ERR_EOF,
|
|
||||||
MIE_ERR_BAD_SYNTAX,
|
|
||||||
MIE_ERR_BAD_FORMAT,
|
|
||||||
MIE_ERR_NOT_SUPPORTED,
|
|
||||||
MIE_ERR_INVALID_VALUE,
|
|
||||||
MIE_ERR_INTERNAL_FAILURE,
|
|
||||||
MIE_ERR_NO_MEMORY,
|
|
||||||
MIE_ERR_NO_ENTRY,
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API const struct b_error_vendor *mie_error_vendor(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#ifndef MIE_TARGET_SELECT_H_
|
|
||||||
#define MIE_TARGET_SELECT_H_
|
|
||||||
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <mie/status.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
struct mie_target;
|
|
||||||
struct mie_call;
|
|
||||||
struct mie_msg;
|
|
||||||
struct mie_select_builder;
|
|
||||||
struct mie_select_value;
|
|
||||||
|
|
||||||
struct mie_target_select_ops {
|
|
||||||
size_t (*s_node_name)(
|
|
||||||
const struct mie_target *, unsigned int, char *, size_t);
|
|
||||||
enum mie_status (*s_lower_call)(
|
|
||||||
const struct mie_target *, struct mie_select_builder *,
|
|
||||||
struct mie_call *, struct mie_select_value *);
|
|
||||||
enum mie_status (*s_lower_msg)(
|
|
||||||
const struct mie_target *, struct mie_select_builder *,
|
|
||||||
struct mie_msg *, struct mie_select_value *);
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API size_t mie_target_select_node_name(
|
|
||||||
const struct mie_target *target, unsigned int opcode, char *out,
|
|
||||||
size_t max);
|
|
||||||
|
|
||||||
MIE_API enum mie_status mie_target_select_lower_call(
|
|
||||||
const struct mie_target *target, struct mie_select_builder *builder,
|
|
||||||
struct mie_call *call, struct mie_select_value *result);
|
|
||||||
MIE_API enum mie_status mie_target_select_lower_msg(
|
|
||||||
const struct mie_target *target, struct mie_select_builder *builder,
|
|
||||||
struct mie_msg *msg, struct mie_select_value *result);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#ifndef MIE_TARGET_TARGET_H_
|
|
||||||
#define MIE_TARGET_TARGET_H_
|
|
||||||
|
|
||||||
#include <mie/misc.h>
|
|
||||||
#include <mie/target/select.h>
|
|
||||||
|
|
||||||
struct mie_target {
|
|
||||||
const char *t_name;
|
|
||||||
const struct mie_target_select_ops *t_select;
|
|
||||||
};
|
|
||||||
|
|
||||||
MIE_API const struct mie_target *mie_target_builtin(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#ifndef MIE_TYPE_H_
|
|
||||||
#define MIE_TYPE_H_
|
|
||||||
|
|
||||||
#define MIE_TYPE(p) ((struct mie_type *)(p))
|
|
||||||
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
|
|
||||||
enum mie_type_id {
|
|
||||||
MIE_TYPE_VOID = 0x00u,
|
|
||||||
MIE_TYPE_INT = 0x01u,
|
|
||||||
MIE_TYPE_PTR = 0x02u,
|
|
||||||
MIE_TYPE_ID = 0x03u,
|
|
||||||
MIE_TYPE_STR = 0x04u,
|
|
||||||
MIE_TYPE_ATOM = 0x05u,
|
|
||||||
MIE_TYPE_CLASS = 0x06u,
|
|
||||||
MIE_TYPE_ARRAY = 0x08u,
|
|
||||||
MIE_TYPE_LABEL = 0x09u,
|
|
||||||
MIE_TYPE_SELECTOR = 0x0Au,
|
|
||||||
MIE_TYPE_FUNC = 0x0Bu,
|
|
||||||
MIE_TYPE_GLUE = 0xFEu,
|
|
||||||
MIE_TYPE_OTHER = 0xFFu,
|
|
||||||
__MIE_TYPE_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_type {
|
|
||||||
struct mie_value t_base;
|
|
||||||
enum mie_type_id t_id;
|
|
||||||
unsigned int t_count;
|
|
||||||
|
|
||||||
union {
|
|
||||||
unsigned int t_width;
|
|
||||||
b_queue t_vars;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct mie_type *mie_type_create(void);
|
|
||||||
|
|
||||||
MIE_API void mie_type_to_string(const struct mie_type *type, char *out, size_t max);
|
|
||||||
MIE_API bool mie_type_compare(const struct mie_type *a, const struct mie_type *b);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
30
mie/ir/arg.c
30
mie/ir/arg.c
@@ -1,30 +0,0 @@
|
|||||||
#include <mie/ir/arg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_arg *mie_arg_create(struct mie_type *type)
|
|
||||||
{
|
|
||||||
struct mie_arg *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
mie_value_init(&out->arg_base, MIE_VALUE_ARG);
|
|
||||||
|
|
||||||
out->arg_type = type;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_arg *arg = MIE_ARG(v);
|
|
||||||
return arg->arg_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type arg_value_type = {
|
|
||||||
.t_id = MIE_VALUE_ARG,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
};
|
|
||||||
104
mie/ir/block.c
104
mie/ir/block.c
@@ -1,104 +0,0 @@
|
|||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/block.h>
|
|
||||||
#include <mie/ir/func.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
struct mie_block *mie_block_create(struct mie_func *parent, const char *name)
|
|
||||||
{
|
|
||||||
struct mie_block *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
mie_value_init(&out->b_base, MIE_VALUE_BLOCK);
|
|
||||||
|
|
||||||
struct mie_value *block = MIE_VALUE(out);
|
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
block = mie_func_generate_value_name(parent, block, name);
|
|
||||||
if (!block) {
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&parent->f_blocks, &block->v_entry);
|
|
||||||
out->b_parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mie_block_add_instr(struct mie_block *block, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
switch (instr->i_type) {
|
|
||||||
case MIE_INSTR_PHI:
|
|
||||||
if (!b_queue_empty(&block->b_instr) || block->b_terminator) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&block->b_phi, &instr->i_base.v_entry);
|
|
||||||
return true;
|
|
||||||
case MIE_INSTR_RET:
|
|
||||||
case MIE_INSTR_BR:
|
|
||||||
case MIE_INSTR_SWITCH:
|
|
||||||
if (block->b_terminator) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
block->b_terminator = instr;
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
if (block->b_terminator) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&block->b_instr, &instr->i_base.v_entry);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
return mie_ctx_get_type(ctx, MIE_TYPE_LABEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup(struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_block *block = MIE_BLOCK(value);
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&block->b_phi);
|
|
||||||
b_queue_entry *next = NULL;
|
|
||||||
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&block->b_phi, entry);
|
|
||||||
mie_value_destroy(v);
|
|
||||||
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&block->b_instr);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&block->b_instr, entry);
|
|
||||||
mie_value_destroy(v);
|
|
||||||
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block->b_terminator) {
|
|
||||||
mie_value_destroy(MIE_VALUE(block->b_terminator));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type block_value_type = {
|
|
||||||
.t_id = MIE_VALUE_BLOCK,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
.t_cleanup = cleanup,
|
|
||||||
};
|
|
||||||
834
mie/ir/builder.c
834
mie/ir/builder.c
@@ -1,834 +0,0 @@
|
|||||||
#include <blue/ds/string.h>
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/alloca.h>
|
|
||||||
#include <mie/ir/block.h>
|
|
||||||
#include <mie/ir/branch.h>
|
|
||||||
#include <mie/ir/builder.h>
|
|
||||||
#include <mie/ir/data.h>
|
|
||||||
#include <mie/ir/func.h>
|
|
||||||
#include <mie/ir/module.h>
|
|
||||||
#include <mie/ir/msg.h>
|
|
||||||
#include <mie/ir/op.h>
|
|
||||||
#include <mie/ir/phi.h>
|
|
||||||
#include <mie/ir/ptr.h>
|
|
||||||
#include <mie/ir/record.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_module *mod)
|
|
||||||
{
|
|
||||||
struct mie_builder *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
out->b_ctx = ctx;
|
|
||||||
out->b_module = mod;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_builder_destroy(struct mie_builder *builder)
|
|
||||||
{
|
|
||||||
free(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_func *mie_builder_get_current_func(struct mie_builder *builder)
|
|
||||||
{
|
|
||||||
struct mie_block *block = builder->b_current_block;
|
|
||||||
if (!block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return block->b_parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_record *mie_builder_put_record(
|
|
||||||
struct mie_builder *builder, struct mie_const *val, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_module) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&builder->b_module->m_records);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *rec = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
|
|
||||||
if (!strcmp(rec->v_name.n_str, name)) {
|
|
||||||
/* TODO what to do about `val` here? */
|
|
||||||
return MIE_RECORD(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_record *rec = mie_record_create(val);
|
|
||||||
rec->r_base.v_name.n_str = b_strdup(name);
|
|
||||||
b_queue_push_back(&builder->b_module->m_records, &rec->r_base.v_entry);
|
|
||||||
|
|
||||||
return rec;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_record *mie_builder_get_record(
|
|
||||||
struct mie_builder *builder, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_module) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&builder->b_module->m_records);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *rec = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
|
|
||||||
if (!strcmp(rec->v_name.n_str, name)) {
|
|
||||||
return MIE_RECORD(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data)
|
|
||||||
{
|
|
||||||
if (!builder->b_module) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *data_name = data->d_base.v_name.n_str;
|
|
||||||
struct mie_data *v = mie_module_get_data(builder->b_module, data_name);
|
|
||||||
if (v) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_module_put_data(builder->b_module, data);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type)
|
|
||||||
{
|
|
||||||
if (!builder->b_module) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *type_name = type->t_base.v_name.n_str;
|
|
||||||
struct mie_data *v = mie_module_get_data(builder->b_module, type_name);
|
|
||||||
if (v) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_module_put_data(builder->b_module, MIE_VALUE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void mie_builder_set_insert_point(
|
|
||||||
struct mie_builder *builder, struct mie_block *block)
|
|
||||||
{
|
|
||||||
builder->b_current_block = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_get_data_ptr(
|
|
||||||
struct mie_builder *builder, const char *data_ident)
|
|
||||||
{
|
|
||||||
if (!builder->b_module) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_data *data = mie_module_get_data(builder->b_module, data_ident);
|
|
||||||
if (!data) {
|
|
||||||
struct mie_type *id
|
|
||||||
= mie_ctx_get_type(builder->b_ctx, MIE_TYPE_ID);
|
|
||||||
data = mie_data_create_extern_global(id, data_ident);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_module_put_data(builder->b_module, data, data_ident);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_get_string_ptr(
|
|
||||||
struct mie_builder *builder, const char *s)
|
|
||||||
{
|
|
||||||
if (!builder->b_module) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_data *data = mie_module_get_string_ptr(builder->b_module, s);
|
|
||||||
if (!data) {
|
|
||||||
struct mie_type *str
|
|
||||||
= mie_ctx_get_type(builder->b_ctx, MIE_TYPE_STR);
|
|
||||||
struct mie_value *value = mie_ctx_get_string(builder->b_ctx, s);
|
|
||||||
|
|
||||||
data = mie_data_create_const((struct mie_const *)value);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_module_put_data(builder->b_module, data, ".str");
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_ret(struct mie_builder *builder, struct mie_value *val)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_ret *ret = malloc(sizeof *ret);
|
|
||||||
if (!ret) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_instr_init(&ret->r_base, MIE_INSTR_RET);
|
|
||||||
ret->r_val = val;
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &ret->r_base)) {
|
|
||||||
free(ret);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_add(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *add = malloc(sizeof *add);
|
|
||||||
if (!add) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(add, 0x0, sizeof *add);
|
|
||||||
|
|
||||||
mie_instr_init(&add->op_base, MIE_INSTR_ADD);
|
|
||||||
|
|
||||||
add->op_left = left;
|
|
||||||
add->op_right = right;
|
|
||||||
add->op_type = mie_value_get_type(left, builder->b_ctx);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &add->op_base)) {
|
|
||||||
free(add);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(add), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(add);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_sub(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_SUB);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_value_get_type(left, builder->b_ctx);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_mul(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *mul = malloc(sizeof *mul);
|
|
||||||
if (!mul) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(mul, 0x0, sizeof *mul);
|
|
||||||
|
|
||||||
mie_instr_init(&mul->op_base, MIE_INSTR_MUL);
|
|
||||||
|
|
||||||
mul->op_left = left;
|
|
||||||
mul->op_right = right;
|
|
||||||
mul->op_type = mie_value_get_type(left, builder->b_ctx);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &mul->op_base)) {
|
|
||||||
free(mul);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(mul), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(mul);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_div(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *div = malloc(sizeof *div);
|
|
||||||
if (!div) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(div, 0x0, sizeof *div);
|
|
||||||
|
|
||||||
mie_instr_init(&div->op_base, MIE_INSTR_DIV);
|
|
||||||
|
|
||||||
div->op_left = left;
|
|
||||||
div->op_right = right;
|
|
||||||
div->op_type = mie_value_get_type(left, builder->b_ctx);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &div->op_base)) {
|
|
||||||
free(div);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(div), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(div);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_load(
|
|
||||||
struct mie_builder *builder, struct mie_type *type,
|
|
||||||
struct mie_value *src, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_load *load = malloc(sizeof *load);
|
|
||||||
if (!load) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_instr_init(&load->l_base, MIE_INSTR_LOAD);
|
|
||||||
load->l_src = src;
|
|
||||||
load->l_type = type;
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &load->l_base)) {
|
|
||||||
free(load);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(load), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(load);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_store(
|
|
||||||
struct mie_builder *builder, struct mie_value *val, struct mie_value *dest)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_store *store = malloc(sizeof *store);
|
|
||||||
if (!store) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_instr_init(&store->s_base, MIE_INSTR_STORE);
|
|
||||||
store->s_val = val;
|
|
||||||
store->s_dest = dest;
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &store->s_base)) {
|
|
||||||
free(store);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_alloca(
|
|
||||||
struct mie_builder *builder, struct mie_type *type, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_alloca *alloca = malloc(sizeof *alloca);
|
|
||||||
if (!alloca) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_instr_init(&alloca->a_base, MIE_INSTR_ALLOCA);
|
|
||||||
alloca->a_type = type;
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &alloca->a_base)) {
|
|
||||||
free(alloca);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(alloca), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(alloca);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_switch(
|
|
||||||
struct mie_builder *builder, struct mie_value *cond,
|
|
||||||
struct mie_switch_branch *branches, size_t nr_branches,
|
|
||||||
struct mie_block *default_block)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_br(struct mie_builder *builder, struct mie_block *dest)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_branch *br = malloc(sizeof *br);
|
|
||||||
if (!br) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(br, 0x0, sizeof *br);
|
|
||||||
|
|
||||||
mie_instr_init(&br->b_base, MIE_INSTR_BR);
|
|
||||||
|
|
||||||
br->b_dest = dest;
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &br->b_base)) {
|
|
||||||
free(br);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(br);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_br_if(
|
|
||||||
struct mie_builder *builder, struct mie_value *cond,
|
|
||||||
struct mie_block *if_true, struct mie_block *if_false)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_branch_if *br = malloc(sizeof *br);
|
|
||||||
if (!br) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(br, 0x0, sizeof *br);
|
|
||||||
|
|
||||||
mie_instr_init(&br->b_base, MIE_INSTR_BR_IF);
|
|
||||||
|
|
||||||
br->b_cond = cond;
|
|
||||||
br->b_true_block = if_true;
|
|
||||||
br->b_false_block = if_false;
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &br->b_base)) {
|
|
||||||
free(br);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(br);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_msg(
|
|
||||||
struct mie_builder *builder, struct mie_type *ret_type,
|
|
||||||
struct mie_value *recipient, struct mie_value *selector,
|
|
||||||
struct mie_value **args, size_t nr_args, enum mie_builder_flags flags,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & MIE_BUILDER_IGNORE_RESULT) && name) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_msg *msg = malloc(sizeof *msg);
|
|
||||||
if (!msg) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(msg, 0x0, sizeof *msg);
|
|
||||||
|
|
||||||
mie_instr_init(&msg->msg_base, MIE_INSTR_MSG);
|
|
||||||
|
|
||||||
msg->msg_ret_type = ret_type;
|
|
||||||
msg->msg_recipient = recipient;
|
|
||||||
msg->msg_selector = selector;
|
|
||||||
|
|
||||||
msg->msg_nr_args = nr_args;
|
|
||||||
msg->msg_args = calloc(nr_args, sizeof(struct mie_value *));
|
|
||||||
memcpy(msg->msg_args, args, nr_args * sizeof(struct mie_value *));
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &msg->msg_base)) {
|
|
||||||
free(msg);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & MIE_BUILDER_IGNORE_RESULT)) {
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(msg), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MIE_VALUE(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_cmp_eq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_CMP_EQ);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_cmp_neq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_CMP_NEQ);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_cmp_lt(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_CMP_LT);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_cmp_gt(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_CMP_GT);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_cmp_leq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_CMP_LEQ);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_cmp_geq(
|
|
||||||
struct mie_builder *builder, struct mie_value *left,
|
|
||||||
struct mie_value *right, const char *name)
|
|
||||||
{
|
|
||||||
if (!builder->b_current_block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_current_block->b_terminator) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
||||||
if (!sub) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sub, 0x0, sizeof *sub);
|
|
||||||
|
|
||||||
mie_instr_init(&sub->op_base, MIE_INSTR_CMP_GEQ);
|
|
||||||
|
|
||||||
sub->op_left = left;
|
|
||||||
sub->op_right = right;
|
|
||||||
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
||||||
free(sub);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_getelementptr(
|
|
||||||
struct mie_builder *builder, struct mie_type *container_type,
|
|
||||||
struct mie_value *container, struct mie_value *index, const char *name)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_setelementptr(
|
|
||||||
struct mie_builder *builder, struct mie_type *container_type,
|
|
||||||
struct mie_value *container, struct mie_value *index)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_builder_phi(
|
|
||||||
struct mie_builder *builder, struct mie_type *type,
|
|
||||||
struct mie_phi_edge *edges, unsigned int nr_edges, const char *name)
|
|
||||||
{
|
|
||||||
struct mie_block *block = builder->b_current_block;
|
|
||||||
|
|
||||||
if (!block) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block->b_terminator || !b_queue_empty(&block->b_instr)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_phi *phi = malloc(sizeof *phi);
|
|
||||||
if (!phi) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(phi, 0x0, sizeof *phi);
|
|
||||||
|
|
||||||
mie_instr_init(&phi->p_base, MIE_INSTR_PHI);
|
|
||||||
|
|
||||||
phi->p_type = type;
|
|
||||||
phi->p_nr_edges = nr_edges;
|
|
||||||
phi->p_edges = calloc(nr_edges, sizeof(struct mie_phi_edge));
|
|
||||||
if (!phi->p_edges) {
|
|
||||||
free(phi);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(phi->p_edges, edges, nr_edges * sizeof(struct mie_phi_edge));
|
|
||||||
|
|
||||||
if (!mie_block_add_instr(builder->b_current_block, &phi->p_base)) {
|
|
||||||
free(phi);
|
|
||||||
free(phi->p_edges);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_func_generate_value_name(
|
|
||||||
builder->b_current_block->b_parent, MIE_VALUE(phi), name);
|
|
||||||
|
|
||||||
return MIE_VALUE(phi);
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#include <mie/ir/const.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void mie_const_init(struct mie_const *c, struct mie_type *type)
|
|
||||||
{
|
|
||||||
memset(c, 0x0, sizeof *c);
|
|
||||||
mie_value_init(&c->c_base, MIE_VALUE_CONST);
|
|
||||||
|
|
||||||
c->c_type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_const *c = MIE_CONST(v);
|
|
||||||
return c->c_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type const_value_type = {
|
|
||||||
.t_id = MIE_VALUE_CONST,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#include "convert.h"
|
|
||||||
|
|
||||||
b_status read_value_from_bitcode(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **out)
|
|
||||||
{
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#include "convert.h"
|
|
||||||
|
|
||||||
b_status write_value_to_bitcode(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
#include "convert.h"
|
|
||||||
|
|
||||||
#include <mie/ir/convert.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_ir_converter *mie_ir_converter_create(
|
|
||||||
struct mie_ctx *ctx, enum mie_ir_format src, enum mie_ir_format dest)
|
|
||||||
{
|
|
||||||
if (src == dest) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_ir_converter *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->c_ctx = ctx;
|
|
||||||
out->c_src_format = src;
|
|
||||||
out->c_dest_format = dest;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_ir_converter_destroy(struct mie_ir_converter *converter)
|
|
||||||
{
|
|
||||||
free(converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_src_value(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
if (converter->c_src_format != MIE_IR_MEM) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_src_medium = MIE_IR_CONVERTER_MIE_VALUE;
|
|
||||||
converter->c_src.value = value;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_src_bitbuffer(
|
|
||||||
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer)
|
|
||||||
{
|
|
||||||
if (converter->c_src_format != MIE_IR_BITCODE) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_src_medium = MIE_IR_CONVERTER_BITBUFFER;
|
|
||||||
converter->c_src.bitbuffer = bitbuffer;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_src_stringstream(
|
|
||||||
struct mie_ir_converter *converter, b_stringstream *stringstream)
|
|
||||||
{
|
|
||||||
if (converter->c_src_format != MIE_IR_TEXT) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_src_medium = MIE_IR_CONVERTER_STRINGSTREAM;
|
|
||||||
converter->c_src.stringstream = stringstream;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_src_string(
|
|
||||||
struct mie_ir_converter *converter, b_string *string)
|
|
||||||
{
|
|
||||||
if (converter->c_src_format != MIE_IR_TEXT) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_src_medium = MIE_IR_CONVERTER_STRING;
|
|
||||||
converter->c_src.string = string;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_src_file(struct mie_ir_converter *converter, FILE *file)
|
|
||||||
{
|
|
||||||
if (converter->c_src_format != MIE_IR_TEXT) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_src_medium = MIE_IR_CONVERTER_FILE;
|
|
||||||
converter->c_src.file = file;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_dest_value(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **value)
|
|
||||||
{
|
|
||||||
if (converter->c_dest_format != MIE_IR_MEM) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_dest_medium = MIE_IR_CONVERTER_MIE_VALUE;
|
|
||||||
converter->c_dest.value = value;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_dest_bitbuffer(
|
|
||||||
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer)
|
|
||||||
{
|
|
||||||
if (converter->c_dest_format != MIE_IR_BITCODE) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_dest_medium = MIE_IR_CONVERTER_BITBUFFER;
|
|
||||||
converter->c_dest.bitbuffer = bitbuffer;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_dest_stringstream(
|
|
||||||
struct mie_ir_converter *converter, b_stringstream *stringstream)
|
|
||||||
{
|
|
||||||
if (converter->c_dest_format != MIE_IR_TEXT) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_dest_medium = MIE_IR_CONVERTER_STRINGSTREAM;
|
|
||||||
converter->c_dest.stringstream = stringstream;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_dest_string(
|
|
||||||
struct mie_ir_converter *converter, b_string *string)
|
|
||||||
{
|
|
||||||
if (converter->c_dest_format != MIE_IR_TEXT) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_dest_medium = MIE_IR_CONVERTER_STRING;
|
|
||||||
converter->c_dest.string = string;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_set_dest_file(
|
|
||||||
struct mie_ir_converter *converter, FILE *file)
|
|
||||||
{
|
|
||||||
if (converter->c_dest_format != MIE_IR_TEXT) {
|
|
||||||
return B_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
converter->c_dest_medium = MIE_IR_CONVERTER_FILE;
|
|
||||||
converter->c_dest.file = file;
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status read_value_from_medium(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **value)
|
|
||||||
{
|
|
||||||
switch (converter->c_src_format) {
|
|
||||||
case MIE_IR_MEM:
|
|
||||||
*value = converter->c_src.value;
|
|
||||||
return B_SUCCESS;
|
|
||||||
case MIE_IR_TEXT:
|
|
||||||
return read_value_from_text(converter, value);
|
|
||||||
case MIE_IR_BITCODE:
|
|
||||||
return read_value_from_bitcode(converter, value);
|
|
||||||
default:
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_value_to_medium(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
switch (converter->c_dest_format) {
|
|
||||||
case MIE_IR_MEM:
|
|
||||||
*converter->c_dest.value = value;
|
|
||||||
return B_SUCCESS;
|
|
||||||
case MIE_IR_TEXT:
|
|
||||||
return write_value_to_text(converter, value);
|
|
||||||
case MIE_IR_BITCODE:
|
|
||||||
return write_value_to_bitcode(converter, value);
|
|
||||||
default:
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status mie_ir_converter_process(struct mie_ir_converter *converter)
|
|
||||||
{
|
|
||||||
b_status status = B_SUCCESS;
|
|
||||||
struct mie_value *value = NULL;
|
|
||||||
|
|
||||||
status = read_value_from_medium(converter, &value);
|
|
||||||
|
|
||||||
if (!B_OK(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return B_ERR_BAD_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = write_value_to_medium(converter, value);
|
|
||||||
|
|
||||||
if (converter->c_src_format != MIE_IR_MEM) {
|
|
||||||
mie_value_destroy(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#ifndef _MIE_CONVERT_H_
|
|
||||||
#define _MIE_CONVERT_H_
|
|
||||||
|
|
||||||
#include <mie/ir/convert.h>
|
|
||||||
|
|
||||||
extern b_status write_char(struct mie_ir_converter *converter, char c);
|
|
||||||
extern b_status write_string(struct mie_ir_converter *converter, const char *s);
|
|
||||||
|
|
||||||
extern b_status read_value_from_text(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **out);
|
|
||||||
extern b_status read_value_from_bitcode(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **out);
|
|
||||||
|
|
||||||
extern b_status write_value_to_text(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value);
|
|
||||||
extern b_status write_value_to_bitcode(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#include "convert.h"
|
|
||||||
|
|
||||||
b_status read_value_from_text(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value **out)
|
|
||||||
{
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
@@ -1,747 +0,0 @@
|
|||||||
#include "convert.h"
|
|
||||||
|
|
||||||
#include <blue/ds/hashmap.h>
|
|
||||||
#include <blue/ds/list.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <mie/ir/alloca.h>
|
|
||||||
#include <mie/ir/arg.h>
|
|
||||||
#include <mie/ir/block.h>
|
|
||||||
#include <mie/ir/branch.h>
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/data.h>
|
|
||||||
#include <mie/ir/func.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/ir/module.h>
|
|
||||||
#include <mie/ir/msg.h>
|
|
||||||
#include <mie/ir/op.h>
|
|
||||||
#include <mie/ir/phi.h>
|
|
||||||
#include <mie/ir/ptr.h>
|
|
||||||
#include <mie/ir/record.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#define F_INCLUDE_TYPE 0x01u
|
|
||||||
|
|
||||||
typedef b_status (*write_function)(struct mie_ir_converter *, struct mie_value *);
|
|
||||||
|
|
||||||
b_status write_char(struct mie_ir_converter *converter, char c)
|
|
||||||
{
|
|
||||||
long result = 0;
|
|
||||||
char s[] = {c, '\0'};
|
|
||||||
|
|
||||||
switch (converter->c_dest_medium) {
|
|
||||||
case MIE_IR_CONVERTER_STRINGSTREAM:
|
|
||||||
return b_stream_write_string(
|
|
||||||
converter->c_dest.stringstream, s, NULL);
|
|
||||||
case MIE_IR_CONVERTER_STRING:
|
|
||||||
b_string_append_cstr(converter->c_dest.string, s);
|
|
||||||
return B_SUCCESS;
|
|
||||||
case MIE_IR_CONVERTER_FILE:
|
|
||||||
result = fputc(c, converter->c_dest.file);
|
|
||||||
return result == EOF ? B_ERR_IO_FAILURE : B_SUCCESS;
|
|
||||||
default:
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status write_string(struct mie_ir_converter *converter, const char *s)
|
|
||||||
{
|
|
||||||
long result = 0;
|
|
||||||
|
|
||||||
switch (converter->c_dest_medium) {
|
|
||||||
case MIE_IR_CONVERTER_STRINGSTREAM:
|
|
||||||
return b_stream_write_string(
|
|
||||||
converter->c_dest.stringstream, s, NULL);
|
|
||||||
case MIE_IR_CONVERTER_STRING:
|
|
||||||
b_string_append_cstr(converter->c_dest.string, s);
|
|
||||||
return B_SUCCESS;
|
|
||||||
case MIE_IR_CONVERTER_FILE:
|
|
||||||
result = fputs(s, converter->c_dest.file);
|
|
||||||
return result == EOF ? B_ERR_IO_FAILURE : B_SUCCESS;
|
|
||||||
default:
|
|
||||||
return B_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_status write_string_f(struct mie_ir_converter *converter, const char *format, ...)
|
|
||||||
{
|
|
||||||
long result = 0;
|
|
||||||
|
|
||||||
char buf[512];
|
|
||||||
va_list arg;
|
|
||||||
va_start(arg, format);
|
|
||||||
|
|
||||||
b_status status = B_SUCCESS;
|
|
||||||
|
|
||||||
switch (converter->c_dest_medium) {
|
|
||||||
case MIE_IR_CONVERTER_STRINGSTREAM:
|
|
||||||
vsnprintf(buf, sizeof buf, format, arg);
|
|
||||||
status = b_stream_write_string(
|
|
||||||
converter->c_dest.stringstream, buf, NULL);
|
|
||||||
break;
|
|
||||||
case MIE_IR_CONVERTER_STRING:
|
|
||||||
vsnprintf(buf, sizeof buf, format, arg);
|
|
||||||
b_string_append_cstr(converter->c_dest.string, buf);
|
|
||||||
status = B_SUCCESS;
|
|
||||||
break;
|
|
||||||
case MIE_IR_CONVERTER_FILE:
|
|
||||||
result = vfprintf(converter->c_dest.file, format, arg);
|
|
||||||
status = (result == EOF ? B_ERR_IO_FAILURE : B_SUCCESS);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
status = B_ERR_NOT_SUPPORTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(arg);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand_const(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
struct mie_const *c = MIE_CONST(value);
|
|
||||||
|
|
||||||
if (flags & F_INCLUDE_TYPE) {
|
|
||||||
char type_name[64];
|
|
||||||
mie_type_to_string(c->c_type, type_name, sizeof type_name);
|
|
||||||
write_string_f(converter, "%s", type_name);
|
|
||||||
|
|
||||||
if (type_name[0] != 0) {
|
|
||||||
write_char(converter, ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c->c_type->t_id) {
|
|
||||||
case MIE_TYPE_INT: {
|
|
||||||
struct mie_int *v = MIE_INT(c);
|
|
||||||
write_string_f(converter, "#%" PRId64, v->i_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_PTR:
|
|
||||||
case MIE_TYPE_ID:
|
|
||||||
write_string_f(converter, "%%%s", value->v_name.n_str);
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_STR: {
|
|
||||||
struct mie_string *v = MIE_STRING(c);
|
|
||||||
|
|
||||||
write_string_f(converter, "\"%s\"", v->s_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_ATOM: {
|
|
||||||
struct mie_atom *v = MIE_ATOM(c);
|
|
||||||
|
|
||||||
write_string_f(converter, "\"%s\"", v->a_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_SELECTOR: {
|
|
||||||
struct mie_selector *v = MIE_SELECTOR(c);
|
|
||||||
|
|
||||||
write_string_f(converter, "@%s", v->sel_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_CLASS:
|
|
||||||
write_string_f(converter, "@%s", value->v_name.n_str);
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_ARRAY: {
|
|
||||||
struct mie_array *array = MIE_ARRAY(value);
|
|
||||||
b_iterator *it = b_list_begin(array->a_values);
|
|
||||||
|
|
||||||
write_char(converter, '{');
|
|
||||||
size_t i = 0;
|
|
||||||
b_foreach(void *, item, it)
|
|
||||||
{
|
|
||||||
if (i > 0) {
|
|
||||||
write_char(converter, ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string(converter, "\n ");
|
|
||||||
|
|
||||||
struct mie_value *child = item;
|
|
||||||
write_operand_const(converter, child, F_INCLUDE_TYPE);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_iterator_unref(it);
|
|
||||||
|
|
||||||
if (!b_list_empty(array->a_values)) {
|
|
||||||
write_char(converter, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
write_char(converter, '}');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand_instr(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
struct mie_instr *instr = MIE_INSTR(value);
|
|
||||||
|
|
||||||
if (flags & F_INCLUDE_TYPE) {
|
|
||||||
char type_name[64];
|
|
||||||
struct mie_type *type
|
|
||||||
= mie_value_get_type(value, converter->c_ctx);
|
|
||||||
mie_type_to_string(type, type_name, sizeof type_name);
|
|
||||||
write_string_f(converter, "%s ", type_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, "%%%s", value->v_name.n_str);
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand_block(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
struct mie_block *block = MIE_BLOCK(value);
|
|
||||||
|
|
||||||
if (flags & F_INCLUDE_TYPE) {
|
|
||||||
char type_name[64];
|
|
||||||
struct mie_type *type
|
|
||||||
= mie_value_get_type(value, converter->c_ctx);
|
|
||||||
mie_type_to_string(type, type_name, sizeof type_name);
|
|
||||||
write_string_f(converter, "%s ", type_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, "%%%s", value->v_name.n_str);
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand_data(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
struct mie_const *c = MIE_CONST(value);
|
|
||||||
|
|
||||||
if (flags & F_INCLUDE_TYPE) {
|
|
||||||
write_string(converter, "ptr ");
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, "@%s", value->v_name.n_str);
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand_arg(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
struct mie_arg *arg = MIE_ARG(value);
|
|
||||||
|
|
||||||
if (flags & F_INCLUDE_TYPE) {
|
|
||||||
char type_name[64];
|
|
||||||
mie_type_to_string(arg->arg_type, type_name, sizeof type_name);
|
|
||||||
write_string_f(converter, "%s ", type_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, "%%%s", value->v_name.n_str);
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand_func(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
struct mie_func *func = MIE_FUNC(value);
|
|
||||||
|
|
||||||
if (flags & F_INCLUDE_TYPE) {
|
|
||||||
write_string(converter, "ptr ");
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, "@%s", value->v_name.n_str);
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_operand(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value, int flags)
|
|
||||||
{
|
|
||||||
if (!value) {
|
|
||||||
write_string(converter, "<NULL VALUE PTR>");
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (value->v_type->t_id) {
|
|
||||||
case MIE_VALUE_NONE:
|
|
||||||
write_string(converter, "null");
|
|
||||||
return B_SUCCESS;
|
|
||||||
case MIE_VALUE_CONST:
|
|
||||||
return write_operand_const(converter, value, flags);
|
|
||||||
case MIE_VALUE_INSTR:
|
|
||||||
return write_operand_instr(converter, value, flags);
|
|
||||||
case MIE_VALUE_BLOCK:
|
|
||||||
return write_operand_block(converter, value, flags);
|
|
||||||
case MIE_VALUE_DATA:
|
|
||||||
return write_operand_data(converter, value, flags);
|
|
||||||
case MIE_VALUE_FUNC:
|
|
||||||
return write_operand_func(converter, value, flags);
|
|
||||||
case MIE_VALUE_ARG:
|
|
||||||
return write_operand_arg(converter, value, flags);
|
|
||||||
default:
|
|
||||||
write_string_f(converter, "<unknown-value:%d>", value->v_type->t_id);
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_module(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_module *mod = MIE_MODULE(value);
|
|
||||||
b_status status = B_SUCCESS;
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&mod->m_records);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *record
|
|
||||||
= b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
status = write_value_to_text(converter, record);
|
|
||||||
|
|
||||||
if (!B_OK(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!b_queue_empty(&mod->m_records)) {
|
|
||||||
write_char(converter, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&mod->m_types);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *type = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
status = write_value_to_text(converter, type);
|
|
||||||
|
|
||||||
if (!B_OK(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!b_queue_empty(&mod->m_types)) {
|
|
||||||
write_char(converter, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
b_iterator *it = b_iterator_begin(mod->m_data);
|
|
||||||
b_foreach_ptr(b_hashmap_item, item, it)
|
|
||||||
{
|
|
||||||
struct mie_value *data = item->value.value_data;
|
|
||||||
status = write_value_to_text(converter, data);
|
|
||||||
|
|
||||||
if (!B_OK(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b_iterator_unref(it);
|
|
||||||
|
|
||||||
if (!b_hashmap_is_empty(mod->m_data)) {
|
|
||||||
write_char(converter, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long i = 0;
|
|
||||||
entry = b_queue_first(&mod->m_func);
|
|
||||||
while (entry) {
|
|
||||||
if (i > 0) {
|
|
||||||
write_char(converter, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *func = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
status = write_value_to_text(converter, func);
|
|
||||||
|
|
||||||
if (!B_OK(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_type_definition(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_record(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_record *rec = MIE_RECORD(value);
|
|
||||||
write_string_f(converter, "record %s", rec->r_base.v_name.n_str);
|
|
||||||
|
|
||||||
if (rec->r_value) {
|
|
||||||
write_string(converter, " = ");
|
|
||||||
write_operand_const(
|
|
||||||
converter, MIE_VALUE(rec->r_value), F_INCLUDE_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_char(converter, '\n');
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_func_definition(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_func *func = MIE_FUNC(value);
|
|
||||||
|
|
||||||
char type_name[32];
|
|
||||||
mie_type_to_string(func->f_ret, type_name, sizeof type_name);
|
|
||||||
|
|
||||||
write_string_f(
|
|
||||||
converter, "define %s @%s(", type_name, func->f_base.v_name.n_str);
|
|
||||||
|
|
||||||
unsigned int i = 0;
|
|
||||||
struct b_queue_entry *entry = b_queue_first(&func->f_args);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_arg *arg = (struct mie_arg *)b_unbox(
|
|
||||||
struct mie_value, entry, v_entry);
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
write_string(converter, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_type_to_string(func->f_ret, type_name, sizeof type_name);
|
|
||||||
|
|
||||||
write_string_f(
|
|
||||||
converter, "%s %%%s", type_name,
|
|
||||||
arg->arg_base.v_name.n_str);
|
|
||||||
i++;
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, ")");
|
|
||||||
|
|
||||||
switch (func->f_type) {
|
|
||||||
case MIE_FUNC_STATIC:
|
|
||||||
write_string_f(converter, " static");
|
|
||||||
break;
|
|
||||||
case MIE_FUNC_INSTANCE:
|
|
||||||
write_string_f(converter, " instance");
|
|
||||||
break;
|
|
||||||
case MIE_FUNC_LAMBDA:
|
|
||||||
write_string_f(converter, " lambda");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, " {\n");
|
|
||||||
|
|
||||||
entry = b_queue_first(&func->f_blocks);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *block
|
|
||||||
= b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
write_value_to_text(converter, block);
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string_f(converter, "}\n");
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_block_definition(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_block *block = MIE_BLOCK(value);
|
|
||||||
|
|
||||||
write_string_f(converter, "%s:\n", block->b_base.v_name.n_str);
|
|
||||||
b_queue_entry *entry = b_queue_first(&block->b_phi);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *instr
|
|
||||||
= b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
write_value_to_text(converter, instr);
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&block->b_instr);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *instr
|
|
||||||
= b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
write_value_to_text(converter, instr);
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block->b_terminator) {
|
|
||||||
write_value_to_text(converter, MIE_VALUE(block->b_terminator));
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_instr(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_instr *instr = MIE_INSTR(value);
|
|
||||||
write_string_f(converter, "\t");
|
|
||||||
|
|
||||||
if (instr->i_base.v_name.n_str) {
|
|
||||||
write_string_f(converter, "%%%s = ", instr->i_base.v_name.n_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
char type[128];
|
|
||||||
|
|
||||||
switch (instr->i_type) {
|
|
||||||
case MIE_INSTR_RET: {
|
|
||||||
struct mie_ret *ret = (struct mie_ret *)instr;
|
|
||||||
write_string(converter, "ret ");
|
|
||||||
if (!ret->r_val) {
|
|
||||||
write_string(converter, "void");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_operand(converter, ret->r_val, F_INCLUDE_TYPE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MIE_INSTR_ADD: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "add %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_SUB: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "sub %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_MUL: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "mul %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_DIV: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "div %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_LOAD: {
|
|
||||||
struct mie_load *load = (struct mie_load *)instr;
|
|
||||||
mie_type_to_string(load->l_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "load %s, ", type);
|
|
||||||
write_operand(converter, load->l_src, F_INCLUDE_TYPE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_STORE: {
|
|
||||||
struct mie_store *store = (struct mie_store *)instr;
|
|
||||||
write_string(converter, "store ");
|
|
||||||
write_operand(converter, store->s_val, F_INCLUDE_TYPE);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, store->s_dest, F_INCLUDE_TYPE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_ALLOCA: {
|
|
||||||
struct mie_alloca *alloca = (struct mie_alloca *)instr;
|
|
||||||
mie_type_to_string(alloca->a_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "alloca %s", type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_SWITCH:
|
|
||||||
write_string(converter, "switch");
|
|
||||||
break;
|
|
||||||
case MIE_INSTR_BR: {
|
|
||||||
struct mie_branch *br = (struct mie_branch *)instr;
|
|
||||||
write_string(converter, "br ");
|
|
||||||
write_operand(converter, MIE_VALUE(br->b_dest), F_INCLUDE_TYPE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_BR_IF: {
|
|
||||||
struct mie_branch_if *br = (struct mie_branch_if *)instr;
|
|
||||||
write_string(converter, "br ");
|
|
||||||
write_operand(converter, MIE_VALUE(br->b_cond), F_INCLUDE_TYPE);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(
|
|
||||||
converter, MIE_VALUE(br->b_true_block), F_INCLUDE_TYPE);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(
|
|
||||||
converter, MIE_VALUE(br->b_false_block), F_INCLUDE_TYPE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_MSG: {
|
|
||||||
struct mie_msg *msg = (struct mie_msg *)instr;
|
|
||||||
mie_type_to_string(msg->msg_ret_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "msg %s, ", type);
|
|
||||||
write_operand(converter, msg->msg_recipient, F_INCLUDE_TYPE);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, msg->msg_selector, F_INCLUDE_TYPE);
|
|
||||||
|
|
||||||
if (msg->msg_nr_args == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string(converter, " [");
|
|
||||||
for (size_t i = 0; i < msg->msg_nr_args; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
write_string(converter, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
write_operand(converter, msg->msg_args[i], F_INCLUDE_TYPE);
|
|
||||||
}
|
|
||||||
write_string(converter, "]");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_EQ: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "cmp eq %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_NEQ: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "cmp neq %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_LT: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "cmp lt %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_LEQ: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "cmp leq %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_GT: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "cmp gt %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_GEQ: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
mie_type_to_string(op->op_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "cmp geq %s ", type);
|
|
||||||
write_operand(converter, op->op_left, 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, op->op_right, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_GETELEMENTPTR:
|
|
||||||
write_string(converter, "getelementptr");
|
|
||||||
break;
|
|
||||||
case MIE_INSTR_SETELEMENTPTR:
|
|
||||||
write_string(converter, "setelementptr");
|
|
||||||
break;
|
|
||||||
case MIE_INSTR_PHI: {
|
|
||||||
struct mie_phi *phi = (struct mie_phi *)instr;
|
|
||||||
mie_type_to_string(phi->p_type, type, sizeof type);
|
|
||||||
write_string_f(converter, "phi %s ", type);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < phi->p_nr_edges; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
write_string(converter, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
write_string(converter, "[ ");
|
|
||||||
write_operand(
|
|
||||||
converter,
|
|
||||||
MIE_VALUE(phi->p_edges[i].e_incoming_block), 0);
|
|
||||||
write_string(converter, ", ");
|
|
||||||
write_operand(converter, phi->p_edges[i].e_value, 0);
|
|
||||||
write_string(converter, " ]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
write_string_f(converter, "<unknown>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_char(converter, '\n');
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status write_data(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
char type_name[128];
|
|
||||||
|
|
||||||
struct mie_data *data = MIE_DATA(value);
|
|
||||||
write_string_f(converter, "data @%s = ", value->v_name.n_str);
|
|
||||||
|
|
||||||
switch (data->d_type) {
|
|
||||||
case MIE_DATA_EXTERN_GLOBAL:
|
|
||||||
mie_type_to_string(
|
|
||||||
data->d_extern_global.g_type, type_name, sizeof type_name);
|
|
||||||
write_string_f(converter, "extern global %s", type_name);
|
|
||||||
break;
|
|
||||||
case MIE_DATA_CONST:
|
|
||||||
write_operand_const(
|
|
||||||
converter, MIE_VALUE(data->d_const.c_value),
|
|
||||||
F_INCLUDE_TYPE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write_string(converter, "<unknown>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_char(converter, '\n');
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const write_function value_writers[] = {
|
|
||||||
[MIE_VALUE_MODULE] = write_module,
|
|
||||||
[MIE_VALUE_TYPE] = write_type_definition,
|
|
||||||
[MIE_VALUE_RECORD] = write_record,
|
|
||||||
[MIE_VALUE_FUNC] = write_func_definition,
|
|
||||||
[MIE_VALUE_ARG] = NULL,
|
|
||||||
[MIE_VALUE_BLOCK] = write_block_definition,
|
|
||||||
[MIE_VALUE_INSTR] = write_instr,
|
|
||||||
[MIE_VALUE_DATA] = write_data,
|
|
||||||
[MIE_VALUE_CONST] = NULL,
|
|
||||||
};
|
|
||||||
static const size_t nr_value_printers
|
|
||||||
= sizeof value_writers / sizeof value_writers[0];
|
|
||||||
|
|
||||||
b_status write_value_to_text(
|
|
||||||
struct mie_ir_converter *converter, struct mie_value *value)
|
|
||||||
{
|
|
||||||
write_function writer = value_writers[value->v_type->t_id];
|
|
||||||
return writer(converter, value);
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#include <blue/ds/string.h>
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/data.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_data *mie_data_create_extern_global(
|
|
||||||
struct mie_type *type, const char *ident)
|
|
||||||
{
|
|
||||||
struct mie_data *data = malloc(sizeof *data);
|
|
||||||
if (!data) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(data, 0x0, sizeof *data);
|
|
||||||
|
|
||||||
mie_value_init(&data->d_base, MIE_VALUE_DATA);
|
|
||||||
|
|
||||||
data->d_type = MIE_DATA_EXTERN_GLOBAL;
|
|
||||||
data->d_extern_global.g_type = type;
|
|
||||||
data->d_base.v_name.n_str = b_strdup(ident);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_data *mie_data_create_const(struct mie_const *value)
|
|
||||||
{
|
|
||||||
struct mie_data *data = malloc(sizeof *data);
|
|
||||||
if (!data) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(data, 0x0, sizeof *data);
|
|
||||||
|
|
||||||
mie_value_init(&data->d_base, MIE_VALUE_DATA);
|
|
||||||
|
|
||||||
data->d_type = MIE_DATA_CONST;
|
|
||||||
data->d_const.c_value = value;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
return mie_ctx_get_type(ctx, MIE_TYPE_PTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type data_value_type = {
|
|
||||||
.t_id = MIE_VALUE_DATA,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
};
|
|
||||||
150
mie/ir/func.c
150
mie/ir/func.c
@@ -1,150 +0,0 @@
|
|||||||
#include <blue/core/hash.h>
|
|
||||||
#include <blue/ds/string.h>
|
|
||||||
#include <mie/ir/arg.h>
|
|
||||||
#include <mie/ir/block.h>
|
|
||||||
#include <mie/ir/func.h>
|
|
||||||
#include <mie/name.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_func *mie_func_create(enum mie_func_type type, struct mie_type *ret_type)
|
|
||||||
{
|
|
||||||
struct mie_func *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
mie_value_init(&out->f_base, MIE_VALUE_FUNC);
|
|
||||||
|
|
||||||
out->f_type = type;
|
|
||||||
out->f_ret = ret_type;
|
|
||||||
out->f_names = mie_name_map_create();
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_func_add_arg(
|
|
||||||
struct mie_func *func, struct mie_type *type, const char *name)
|
|
||||||
{
|
|
||||||
struct mie_arg *arg = mie_arg_create(type);
|
|
||||||
if (!arg) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *v
|
|
||||||
= mie_func_generate_value_name(func, MIE_VALUE(arg), name);
|
|
||||||
if (!v) {
|
|
||||||
mie_value_destroy(MIE_VALUE(arg));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&func->f_args, &v->v_entry);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_block *mie_func_create_block(struct mie_func *func, const char *name)
|
|
||||||
{
|
|
||||||
struct mie_block *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
mie_value_init(&out->b_base, MIE_VALUE_BLOCK);
|
|
||||||
|
|
||||||
struct mie_value *block = MIE_VALUE(out);
|
|
||||||
|
|
||||||
block = mie_func_generate_value_name(func, block, name);
|
|
||||||
if (!block) {
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->b_parent = func;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_func_insert_block(
|
|
||||||
struct mie_func *func, struct mie_block *block, struct mie_block *after)
|
|
||||||
{
|
|
||||||
if (after) {
|
|
||||||
b_queue_insert_after(
|
|
||||||
&func->f_blocks, &block->b_base.v_entry,
|
|
||||||
&after->b_base.v_entry);
|
|
||||||
} else {
|
|
||||||
b_queue_push_back(&func->f_blocks, &block->b_base.v_entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_func_generate_value_name(
|
|
||||||
struct mie_func *func, struct mie_value *val, const char *hint)
|
|
||||||
{
|
|
||||||
struct mie_name *name
|
|
||||||
= mie_name_map_put(func->f_names, &val->v_name, hint, 0);
|
|
||||||
return b_unbox(struct mie_value, name, v_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_block *mie_func_get_first_block(struct mie_func *func)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&func->f_blocks);
|
|
||||||
if (!entry) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (struct mie_block *)b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_block *mie_func_get_last_block(struct mie_func *func)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_last(&func->f_blocks);
|
|
||||||
if (!entry) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (struct mie_block *)b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_func *f = MIE_FUNC(v);
|
|
||||||
return f->f_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup(struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_func *func = MIE_FUNC(value);
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&func->f_args);
|
|
||||||
b_queue_entry *next = NULL;
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&func->f_args, entry);
|
|
||||||
|
|
||||||
mie_value_destroy(v);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&func->f_blocks);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&func->f_blocks, entry);
|
|
||||||
|
|
||||||
mie_value_destroy(v);
|
|
||||||
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_name_map_destroy(func->f_names);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type func_value_type = {
|
|
||||||
.t_id = MIE_VALUE_FUNC,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
.t_cleanup = cleanup,
|
|
||||||
};
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/ir/msg.h>
|
|
||||||
#include <mie/ir/op.h>
|
|
||||||
#include <mie/ir/phi.h>
|
|
||||||
#include <mie/ir/ptr.h>
|
|
||||||
|
|
||||||
void mie_instr_init(struct mie_instr *instr, enum mie_instr_type type)
|
|
||||||
{
|
|
||||||
memset(instr, 0x0, sizeof *instr);
|
|
||||||
mie_value_init(&instr->i_base, MIE_VALUE_INSTR);
|
|
||||||
instr->i_type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_instr *instr = MIE_INSTR(v);
|
|
||||||
|
|
||||||
switch (instr->i_type) {
|
|
||||||
case MIE_INSTR_RET: {
|
|
||||||
struct mie_ret *ret = (struct mie_ret *)instr;
|
|
||||||
return mie_value_get_type(ret->r_val, ctx);
|
|
||||||
}
|
|
||||||
case MIE_INSTR_ADD:
|
|
||||||
case MIE_INSTR_SUB:
|
|
||||||
case MIE_INSTR_MUL:
|
|
||||||
case MIE_INSTR_DIV: {
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
return op->op_type;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_CMP_EQ:
|
|
||||||
case MIE_INSTR_CMP_NEQ:
|
|
||||||
case MIE_INSTR_CMP_LT:
|
|
||||||
case MIE_INSTR_CMP_LEQ:
|
|
||||||
case MIE_INSTR_CMP_GT:
|
|
||||||
case MIE_INSTR_CMP_GEQ:
|
|
||||||
return mie_ctx_get_int_type(ctx, 1);
|
|
||||||
case MIE_INSTR_LOAD: {
|
|
||||||
struct mie_load *load = (struct mie_load *)instr;
|
|
||||||
return load->l_type;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_ALLOCA:
|
|
||||||
return mie_ctx_get_type(ctx, MIE_TYPE_PTR);
|
|
||||||
case MIE_INSTR_MSG: {
|
|
||||||
struct mie_msg *msg = (struct mie_msg *)instr;
|
|
||||||
return msg->msg_ret_type;
|
|
||||||
}
|
|
||||||
case MIE_INSTR_PHI: {
|
|
||||||
struct mie_phi *phi = (struct mie_phi *)instr;
|
|
||||||
return phi->p_type;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type instr_value_type = {
|
|
||||||
.t_id = MIE_VALUE_INSTR,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
};
|
|
||||||
154
mie/ir/module.c
154
mie/ir/module.c
@@ -1,154 +0,0 @@
|
|||||||
#include <blue/ds/hashmap.h>
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/data.h>
|
|
||||||
#include <mie/ir/func.h>
|
|
||||||
#include <mie/ir/module.h>
|
|
||||||
#include <mie/type.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_module *mie_module_create(void)
|
|
||||||
{
|
|
||||||
struct mie_module *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
mie_value_init(&out->m_base, MIE_VALUE_MODULE);
|
|
||||||
|
|
||||||
out->m_names = mie_name_map_create();
|
|
||||||
out->m_data = b_hashmap_create(NULL, NULL);
|
|
||||||
out->m_data_strings = b_hashmap_create(NULL, NULL);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_module_add_function(
|
|
||||||
struct mie_module *mod, struct mie_func *func, const char *name)
|
|
||||||
{
|
|
||||||
struct mie_value *v
|
|
||||||
= mie_module_generate_value_name(mod, MIE_VALUE(func), name);
|
|
||||||
if (!v) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&mod->m_func, &v->v_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_data *mie_module_get_string_ptr(struct mie_module *mod, const char *s)
|
|
||||||
{
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_data = s,
|
|
||||||
.key_size = strlen(s),
|
|
||||||
};
|
|
||||||
|
|
||||||
const b_hashmap_value *entry = b_hashmap_get(mod->m_data_strings, &key);
|
|
||||||
if (entry) {
|
|
||||||
return entry->value_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_data *mie_module_get_data(struct mie_module *mod, const char *name)
|
|
||||||
{
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_data = name,
|
|
||||||
.key_size = strlen(name),
|
|
||||||
};
|
|
||||||
|
|
||||||
const b_hashmap_value *entry = b_hashmap_get(mod->m_data, &key);
|
|
||||||
if (entry) {
|
|
||||||
return entry->value_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* don't search m_data_strings, as it is keyed by the string contents
|
|
||||||
* rather than the data entry name, and its entries are duplicated in
|
|
||||||
* m_data anyway */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum b_status mie_module_put_data(
|
|
||||||
struct mie_module *mod, struct mie_data *data, const char *name)
|
|
||||||
{
|
|
||||||
struct mie_value *v
|
|
||||||
= mie_module_generate_value_name(mod, MIE_VALUE(data), name);
|
|
||||||
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_data = v->v_name.n_str,
|
|
||||||
.key_size = strlen(name),
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_value value = {
|
|
||||||
.value_data = data,
|
|
||||||
.value_size = sizeof *data,
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_put(mod->m_data, &key, &value);
|
|
||||||
|
|
||||||
if (data->d_type != MIE_DATA_CONST) {
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_const *const_data = data->d_const.c_value;
|
|
||||||
if (const_data->c_type->t_id == MIE_TYPE_STR) {
|
|
||||||
struct mie_string *s = MIE_STRING(const_data);
|
|
||||||
key.key_data = s->s_value;
|
|
||||||
key.key_size = strlen(key.key_data);
|
|
||||||
b_hashmap_put(mod->m_data_strings, &key, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_value *mie_module_generate_value_name(
|
|
||||||
struct mie_module *mod, struct mie_value *val, const char *hint)
|
|
||||||
{
|
|
||||||
struct mie_name *name
|
|
||||||
= mie_name_map_put(mod->m_names, &val->v_name, hint, 0);
|
|
||||||
return b_unbox(struct mie_value, name, v_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup(struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_module *module = MIE_MODULE(value);
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&module->m_records);
|
|
||||||
b_queue_entry *next = NULL;
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&module->m_records, entry);
|
|
||||||
mie_value_destroy(v);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&module->m_types);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&module->m_types, entry);
|
|
||||||
mie_value_destroy(v);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&module->m_func);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
|
|
||||||
next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&module->m_func, entry);
|
|
||||||
mie_value_destroy(v);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_hashmap_unref(module->m_data_strings);
|
|
||||||
b_hashmap_unref(module->m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type module_value_type = {
|
|
||||||
.t_id = MIE_VALUE_MODULE,
|
|
||||||
.t_cleanup = cleanup,
|
|
||||||
};
|
|
||||||
19
mie/ir/phi.c
19
mie/ir/phi.c
@@ -1,19 +0,0 @@
|
|||||||
#include <mie/ir/phi.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_phi_edge *mie_phi_edge_create(
|
|
||||||
struct mie_block *incoming_block, struct mie_value *value)
|
|
||||||
{
|
|
||||||
struct mie_phi_edge *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->e_incoming_block = incoming_block;
|
|
||||||
out->e_value = value;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#include <mie/ir/record.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_record *mie_record_create(const struct mie_const *val)
|
|
||||||
{
|
|
||||||
struct mie_record *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
mie_value_init(&out->r_base, MIE_VALUE_RECORD);
|
|
||||||
out->r_value = val;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_record *r = MIE_RECORD(v);
|
|
||||||
return r->r_value->c_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type record_value_type = {
|
|
||||||
.t_id = MIE_VALUE_RECORD,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
};
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
const struct mie_value_type null_value_type = {
|
|
||||||
.t_id = MIE_VALUE_NONE,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct mie_value_type module_value_type;
|
|
||||||
extern const struct mie_value_type record_value_type;
|
|
||||||
extern const struct mie_value_type func_value_type;
|
|
||||||
extern const struct mie_value_type arg_value_type;
|
|
||||||
extern const struct mie_value_type block_value_type;
|
|
||||||
extern const struct mie_value_type instr_value_type;
|
|
||||||
extern const struct mie_value_type const_value_type;
|
|
||||||
extern const struct mie_value_type data_value_type;
|
|
||||||
|
|
||||||
static const struct mie_value_type *value_types[] = {
|
|
||||||
[MIE_VALUE_NONE] = &null_value_type,
|
|
||||||
[MIE_VALUE_MODULE] = &module_value_type,
|
|
||||||
[MIE_VALUE_RECORD] = &record_value_type,
|
|
||||||
[MIE_VALUE_FUNC] = &func_value_type,
|
|
||||||
[MIE_VALUE_ARG] = &arg_value_type,
|
|
||||||
[MIE_VALUE_BLOCK] = &block_value_type,
|
|
||||||
[MIE_VALUE_INSTR] = &instr_value_type,
|
|
||||||
[MIE_VALUE_CONST] = &const_value_type,
|
|
||||||
[MIE_VALUE_DATA] = &data_value_type,
|
|
||||||
};
|
|
||||||
static const size_t nr_value_types = sizeof value_types / sizeof value_types[0];
|
|
||||||
|
|
||||||
void mie_value_init(struct mie_value *val, enum mie_value_type_id type)
|
|
||||||
{
|
|
||||||
memset(val, 0x0, sizeof *val);
|
|
||||||
|
|
||||||
val->v_type = value_types[type];
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_value_destroy(struct mie_value *val)
|
|
||||||
{
|
|
||||||
if (val->v_type && val->v_type->t_cleanup) {
|
|
||||||
val->v_type->t_cleanup(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MIE_NAME_VALID(&val->v_name)) {
|
|
||||||
mie_name_destroy(&val->v_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *mie_value_get_type(struct mie_value *val, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
if (val->v_type->t_get_type) {
|
|
||||||
return val->v_type->t_get_type(val, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
234
mie/name.c
234
mie/name.c
@@ -1,234 +0,0 @@
|
|||||||
#include <blue/core/rope.h>
|
|
||||||
#include <blue/ds/string.h>
|
|
||||||
#include <mie/name.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
B_BTREE_DEFINE_SIMPLE_INSERT(struct mie_name_map_entry, e_node, e_hash, put_entry)
|
|
||||||
B_BTREE_DEFINE_SIMPLE_GET(
|
|
||||||
struct mie_name_map_entry, uint64_t, e_node, e_hash, get_entry)
|
|
||||||
|
|
||||||
static struct mie_name_bucket *create_bucket(void)
|
|
||||||
{
|
|
||||||
struct mie_name_bucket *out = malloc(sizeof *out);
|
|
||||||
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->b_base.e_type = MIE_NAME_MAP_E_BUCKET;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy_bucket(struct mie_name_bucket *bucket)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&bucket->b_names);
|
|
||||||
|
|
||||||
while (entry) {
|
|
||||||
b_queue_entry *next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&bucket->b_names, entry);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(bucket);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_name_map *mie_name_map_create(void)
|
|
||||||
{
|
|
||||||
struct mie_name_map *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_name_map_destroy(struct mie_name_map *map)
|
|
||||||
{
|
|
||||||
b_btree_node *node = b_btree_first(&map->m_entries);
|
|
||||||
|
|
||||||
while (node) {
|
|
||||||
struct mie_name_map_entry *entry
|
|
||||||
= b_unbox(struct mie_name_map_entry, node, e_node);
|
|
||||||
b_btree_node *next = b_btree_next(node);
|
|
||||||
b_btree_delete(&map->m_entries, node);
|
|
||||||
if (entry->e_type == MIE_NAME_MAP_E_BUCKET) {
|
|
||||||
struct mie_name_bucket *bucket
|
|
||||||
= (struct mie_name_bucket *)entry;
|
|
||||||
destroy_bucket(bucket);
|
|
||||||
}
|
|
||||||
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status put_name_in_bucket(
|
|
||||||
struct mie_name_bucket *bucket, struct mie_name *name)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&bucket->b_names);
|
|
||||||
|
|
||||||
while (entry) {
|
|
||||||
struct mie_name *cur = (struct mie_name *)b_unbox(
|
|
||||||
struct mie_name_map_entry, entry, e_entry);
|
|
||||||
|
|
||||||
if (!strcmp(cur->n_str, name->n_str)) {
|
|
||||||
return B_ERR_NAME_EXISTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&bucket->b_names, &name->n_base.e_entry);
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static b_status put_name(struct mie_name_map *map, struct mie_name *name)
|
|
||||||
{
|
|
||||||
struct mie_name_map_entry *entry
|
|
||||||
= get_entry(&map->m_entries, name->n_base.e_hash);
|
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
put_entry(&map->m_entries, &name->n_base);
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry->e_type == MIE_NAME_MAP_E_BUCKET) {
|
|
||||||
struct mie_name_bucket *bucket = (struct mie_name_bucket *)entry;
|
|
||||||
return put_name_in_bucket(bucket, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_name *existing_name = (struct mie_name *)entry;
|
|
||||||
|
|
||||||
if (!strcmp(existing_name->n_str, name->n_str)) {
|
|
||||||
return B_ERR_NAME_EXISTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_name_bucket *bucket = create_bucket();
|
|
||||||
if (!bucket) {
|
|
||||||
return B_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_btree_delete(&map->m_entries, &entry->e_node);
|
|
||||||
entry->e_entry = B_QUEUE_ENTRY_INIT;
|
|
||||||
|
|
||||||
bucket->b_base.e_hash = name->n_base.e_hash;
|
|
||||||
b_queue_push_back(&bucket->b_names, &existing_name->n_base.e_entry);
|
|
||||||
b_queue_push_back(&bucket->b_names, &name->n_base.e_entry);
|
|
||||||
|
|
||||||
put_entry(&map->m_entries, &bucket->b_base);
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_name *mie_name_map_put(
|
|
||||||
struct mie_name_map *map, struct mie_name *entry, const char *hint,
|
|
||||||
enum mie_name_map_flags flags)
|
|
||||||
{
|
|
||||||
memset(entry, 0x0, sizeof *entry);
|
|
||||||
entry->n_base.e_type = MIE_NAME_MAP_E_NAME;
|
|
||||||
|
|
||||||
b_rope base = {};
|
|
||||||
|
|
||||||
if (hint) {
|
|
||||||
b_rope_init_cstr_borrowed(&base, hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
char str[256];
|
|
||||||
|
|
||||||
if (hint) {
|
|
||||||
/* first try just the hint on its own */
|
|
||||||
b_rope_to_cstr(&base, str, sizeof str);
|
|
||||||
entry->n_str = str;
|
|
||||||
entry->n_base.e_hash = base.r_v.v_cstr.hash;
|
|
||||||
b_status status = put_name(map, entry);
|
|
||||||
|
|
||||||
if (B_OK(status)) {
|
|
||||||
entry->n_parent = map;
|
|
||||||
entry->n_str = b_strdup(str);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & MIE_NAME_MAP_STRICT) {
|
|
||||||
/* the caller insists that `hint` be used as the name.
|
|
||||||
* such a name already exists, so we can't help them */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* that name already exists, use a suffix to make the name unique.
|
|
||||||
* alternately, no hint was specified, so it's up to us to generate the name */
|
|
||||||
b_rope dot = B_ROPE_CHAR('.');
|
|
||||||
b_rope suffix = B_ROPE_UINT(0);
|
|
||||||
b_rope unique_name;
|
|
||||||
|
|
||||||
if (hint) {
|
|
||||||
const b_rope *parts[] = {&base, &dot, &suffix};
|
|
||||||
b_rope_join(&unique_name, parts, sizeof parts / sizeof parts[0]);
|
|
||||||
} else {
|
|
||||||
b_rope_concat(&unique_name, &base, &suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
if (!hint || hint[0] == '\0') {
|
|
||||||
i = map->m_next_id++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;; i++) {
|
|
||||||
suffix.r_v.v_uint = i;
|
|
||||||
|
|
||||||
b_rope_to_cstr(&unique_name, str, sizeof str);
|
|
||||||
|
|
||||||
entry->n_str = str;
|
|
||||||
entry->n_base.e_hash = b_hash_cstr(str);
|
|
||||||
b_status status = put_name(map, entry);
|
|
||||||
|
|
||||||
if (B_OK(status)) {
|
|
||||||
entry->n_parent = map;
|
|
||||||
entry->n_str = b_strdup(str);
|
|
||||||
b_rope_destroy(&unique_name);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b_rope_destroy(&unique_name);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_name_destroy(struct mie_name *name)
|
|
||||||
{
|
|
||||||
struct mie_name_map *parent = name->n_parent;
|
|
||||||
struct mie_name_map_entry *entry
|
|
||||||
= get_entry(&parent->m_entries, name->n_base.e_hash);
|
|
||||||
struct mie_name_bucket *bucket = NULL;
|
|
||||||
if (!entry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (entry->e_type) {
|
|
||||||
case MIE_NAME_MAP_E_NAME:
|
|
||||||
b_btree_delete(&parent->m_entries, &entry->e_node);
|
|
||||||
break;
|
|
||||||
case MIE_NAME_MAP_E_BUCKET:
|
|
||||||
bucket = b_unbox(struct mie_name_bucket, entry, b_base);
|
|
||||||
b_queue_delete(&bucket->b_names, &name->n_base.e_entry);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
name->n_parent = NULL;
|
|
||||||
|
|
||||||
if (name->n_str) {
|
|
||||||
free(name->n_str);
|
|
||||||
name->n_str = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/alloca.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
|
|
||||||
static enum mie_status push(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
struct mie_alloca *alloca = (struct mie_alloca *)instr;
|
|
||||||
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
|
|
||||||
|
|
||||||
struct mie_type *ptr_type = mie_ctx_get_type(
|
|
||||||
mie_select_builder_get_ctx(builder), MIE_TYPE_PTR);
|
|
||||||
struct mie_select_node *frame_index;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_FRAME_INDEX, NULL, 0,
|
|
||||||
&ptr_type, 1, &frame_index);
|
|
||||||
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame_index->n_flags = MIE_SELECT_NODE_F_IVALUE;
|
|
||||||
frame_index->n_value.i = graph->g_frame_index++;
|
|
||||||
|
|
||||||
struct mie_select_value frame_index_value;
|
|
||||||
mie_select_node_get_value(frame_index, ptr_type, 0, &frame_index_value);
|
|
||||||
|
|
||||||
return mie_select_builder_set_value(
|
|
||||||
builder, MIE_VALUE(instr), &frame_index_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct select_instr_type select_alloca = {
|
|
||||||
.i_push = push,
|
|
||||||
};
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <mie/ir/op.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
|
|
||||||
#define DEFINE_PUSH_FUNCTION(name, op) \
|
|
||||||
static enum mie_status push_##name( \
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr) \
|
|
||||||
{ \
|
|
||||||
return push_op(op, builder, instr); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_OP(name) \
|
|
||||||
struct select_instr_type select_##name = { \
|
|
||||||
.i_push = push_##name, \
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status push_op(
|
|
||||||
unsigned int opcode, struct mie_select_builder *builder,
|
|
||||||
struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
struct mie_binary_op *op = (struct mie_binary_op *)instr;
|
|
||||||
|
|
||||||
struct mie_select_value *operands[] = {
|
|
||||||
mie_select_builder_get_value(builder, op->op_left),
|
|
||||||
mie_select_builder_get_value(builder, op->op_right),
|
|
||||||
};
|
|
||||||
size_t nr_operands = sizeof operands / sizeof operands[0];
|
|
||||||
|
|
||||||
struct mie_type *result[] = {
|
|
||||||
op->op_type,
|
|
||||||
};
|
|
||||||
size_t nr_results = sizeof result / sizeof result[0];
|
|
||||||
|
|
||||||
struct mie_select_node *node;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
mie_select_builder_get_graph(builder), mie_target_builtin(),
|
|
||||||
opcode, operands, nr_operands, result, nr_results, &node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value value;
|
|
||||||
mie_select_node_get_value(node, op->op_type, 0, &value);
|
|
||||||
|
|
||||||
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_PUSH_FUNCTION(add, MIE_SELECT_OP_ADD);
|
|
||||||
DEFINE_PUSH_FUNCTION(sub, MIE_SELECT_OP_SUB);
|
|
||||||
DEFINE_PUSH_FUNCTION(mul, MIE_SELECT_OP_MUL);
|
|
||||||
DEFINE_PUSH_FUNCTION(div, MIE_SELECT_OP_DIV);
|
|
||||||
DEFINE_PUSH_FUNCTION(cmp_eq, MIE_SELECT_OP_CMP_EQ);
|
|
||||||
DEFINE_PUSH_FUNCTION(cmp_neq, MIE_SELECT_OP_CMP_NEQ);
|
|
||||||
DEFINE_PUSH_FUNCTION(cmp_lt, MIE_SELECT_OP_CMP_LT);
|
|
||||||
DEFINE_PUSH_FUNCTION(cmp_gt, MIE_SELECT_OP_CMP_GT);
|
|
||||||
DEFINE_PUSH_FUNCTION(cmp_leq, MIE_SELECT_OP_CMP_LEQ);
|
|
||||||
DEFINE_PUSH_FUNCTION(cmp_geq, MIE_SELECT_OP_CMP_GEQ);
|
|
||||||
|
|
||||||
DEFINE_OP(add);
|
|
||||||
DEFINE_OP(sub);
|
|
||||||
DEFINE_OP(mul);
|
|
||||||
DEFINE_OP(div);
|
|
||||||
DEFINE_OP(cmp_eq);
|
|
||||||
DEFINE_OP(cmp_neq);
|
|
||||||
DEFINE_OP(cmp_lt);
|
|
||||||
DEFINE_OP(cmp_gt);
|
|
||||||
DEFINE_OP(cmp_leq);
|
|
||||||
DEFINE_OP(cmp_geq);
|
|
||||||
171
mie/select/br.c
171
mie/select/br.c
@@ -1,171 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/branch.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
|
|
||||||
static enum mie_status get_block_node(
|
|
||||||
struct mie_select_builder *builder, struct mie_block *block,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
struct mie_select_node *block_node = NULL;
|
|
||||||
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
|
|
||||||
struct mie_type *ptr_type = mie_ctx_get_type(
|
|
||||||
mie_select_builder_get_ctx(builder), MIE_TYPE_PTR);
|
|
||||||
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_BLOCK, NULL, 0,
|
|
||||||
&ptr_type, 1, &block_node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
block_node->n_value.v = MIE_VALUE(block);
|
|
||||||
block_node->n_flags |= MIE_SELECT_NODE_F_PVALUE;
|
|
||||||
|
|
||||||
return mie_select_node_get_value(block_node, ptr_type, 0, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status create_br_cond(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *cond,
|
|
||||||
struct mie_select_value *incoming_chain, struct mie_block *dest_block,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
|
|
||||||
|
|
||||||
if (!incoming_chain || !incoming_chain->v_node) {
|
|
||||||
incoming_chain = mie_select_builder_get_mem_access(builder, cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!incoming_chain || !incoming_chain->v_node) {
|
|
||||||
incoming_chain = &graph->g_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value dest;
|
|
||||||
enum mie_status status = get_block_node(builder, dest_block, &dest);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *operands[] = {
|
|
||||||
incoming_chain,
|
|
||||||
mie_select_builder_get_value(builder, cond),
|
|
||||||
&dest,
|
|
||||||
};
|
|
||||||
size_t nr_operands = sizeof operands / sizeof operands[0];
|
|
||||||
|
|
||||||
struct mie_type *chain_type = mie_ctx_get_type(
|
|
||||||
mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER);
|
|
||||||
|
|
||||||
struct mie_select_node *br_node = NULL;
|
|
||||||
|
|
||||||
status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_BR_COND, operands,
|
|
||||||
nr_operands, &chain_type, 1, &br_node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_select_node_get_value(br_node, chain_type, 0, out);
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status create_br(
|
|
||||||
struct mie_select_builder *builder, struct mie_block *dest_block,
|
|
||||||
struct mie_select_value *incoming_chain, struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
|
|
||||||
if (!incoming_chain || !incoming_chain->v_node) {
|
|
||||||
incoming_chain = &graph->g_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value dest;
|
|
||||||
enum mie_status status = get_block_node(builder, dest_block, &dest);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *operands[] = {
|
|
||||||
incoming_chain,
|
|
||||||
&dest,
|
|
||||||
};
|
|
||||||
size_t nr_operands = sizeof operands / sizeof operands[0];
|
|
||||||
|
|
||||||
struct mie_type *chain_type = mie_ctx_get_type(
|
|
||||||
mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER);
|
|
||||||
|
|
||||||
struct mie_select_node *br_node = NULL;
|
|
||||||
|
|
||||||
status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_BR, operands,
|
|
||||||
nr_operands, &chain_type, 1, &br_node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_select_node_get_value(br_node, chain_type, 0, out);
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status push_br(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
struct mie_branch *br = (struct mie_branch *)instr;
|
|
||||||
|
|
||||||
struct mie_select_value incoming_chain = {};
|
|
||||||
enum mie_status status = mie_select_builder_collapse_chain_ends(
|
|
||||||
builder, &incoming_chain);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value br_result;
|
|
||||||
status = create_br(builder, br->b_dest, &incoming_chain, &br_result);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &br_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status push_br_if(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
struct mie_branch_if *br = (struct mie_branch_if *)instr;
|
|
||||||
|
|
||||||
struct mie_select_value incoming_chain = {};
|
|
||||||
enum mie_status status = mie_select_builder_collapse_chain_ends(
|
|
||||||
builder, &incoming_chain);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value br_true_result, br_false_result;
|
|
||||||
status = create_br_cond(
|
|
||||||
builder, br->b_cond, &incoming_chain, br->b_true_block,
|
|
||||||
&br_true_result);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = create_br(
|
|
||||||
builder, br->b_false_block, &br_true_result, &br_false_result);
|
|
||||||
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mie_select_builder_set_value(
|
|
||||||
builder, MIE_VALUE(instr), &br_false_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct select_instr_type select_br = {
|
|
||||||
.i_push = push_br,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct select_instr_type select_br_if = {
|
|
||||||
.i_push = push_br_if,
|
|
||||||
};
|
|
||||||
@@ -1,485 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <blue/ds/hashmap.h>
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/data.h>
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/select/builder.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
#include <mie/target/target.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_select_builder {
|
|
||||||
struct mie_ctx *b_ctx;
|
|
||||||
struct mie_select_graph *b_graph;
|
|
||||||
const struct mie_target *b_target;
|
|
||||||
/* map of mie_instr* to mie_select_value*, defining the graph node that
|
|
||||||
* corresponds to each value-producing instruction */
|
|
||||||
b_hashmap *b_nodes;
|
|
||||||
/* map of mie_instr* to mie_select_value*, defining the graph node that
|
|
||||||
* last accessed a memory location defined by a particular instruction. */
|
|
||||||
b_hashmap *b_mem_access;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_select_builder *mie_select_builder_create(
|
|
||||||
struct mie_ctx *ctx, const struct mie_target *target)
|
|
||||||
{
|
|
||||||
struct mie_select_builder *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->b_ctx = ctx;
|
|
||||||
out->b_target = target;
|
|
||||||
out->b_graph = mie_select_graph_create(ctx);
|
|
||||||
if (!out->b_graph) {
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->b_nodes = b_hashmap_create(NULL, NULL);
|
|
||||||
if (!out->b_nodes) {
|
|
||||||
mie_select_graph_destroy(out->b_graph);
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->b_mem_access = b_hashmap_create(NULL, NULL);
|
|
||||||
if (!out->b_mem_access) {
|
|
||||||
b_hashmap_unref(out->b_nodes);
|
|
||||||
mie_select_graph_destroy(out->b_graph);
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_builder_destroy(struct mie_select_builder *builder)
|
|
||||||
{
|
|
||||||
if (builder->b_nodes) {
|
|
||||||
b_hashmap_unref(builder->b_nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_mem_access) {
|
|
||||||
b_hashmap_unref(builder->b_mem_access);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder->b_graph) {
|
|
||||||
mie_select_graph_destroy(builder->b_graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_graph *mie_select_builder_get_graph(
|
|
||||||
struct mie_select_builder *builder)
|
|
||||||
{
|
|
||||||
return builder->b_graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_ctx *mie_select_builder_get_ctx(struct mie_select_builder *builder)
|
|
||||||
{
|
|
||||||
return builder->b_ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_target *mie_select_builder_get_target(
|
|
||||||
struct mie_select_builder *builder)
|
|
||||||
{
|
|
||||||
return builder->b_target;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_graph *mie_select_builder_finish(struct mie_select_builder *builder)
|
|
||||||
{
|
|
||||||
enum mie_status status = MIE_SUCCESS;
|
|
||||||
struct mie_select_graph *graph = builder->b_graph;
|
|
||||||
|
|
||||||
struct mie_select_value *root_operands[] = {
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
size_t nr_root_operands = 0;
|
|
||||||
|
|
||||||
struct mie_select_value incoming_chain = {};
|
|
||||||
status = mie_select_builder_collapse_chain_ends(builder, &incoming_chain);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (incoming_chain.v_node) {
|
|
||||||
root_operands[0] = &incoming_chain;
|
|
||||||
nr_root_operands++;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_ROOT, root_operands,
|
|
||||||
nr_root_operands, NULL, 0, &graph->g_root);
|
|
||||||
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_hashmap_unref(builder->b_nodes);
|
|
||||||
builder->b_nodes = b_hashmap_create(NULL, NULL);
|
|
||||||
|
|
||||||
b_hashmap_unref(builder->b_mem_access);
|
|
||||||
builder->b_mem_access = b_hashmap_create(NULL, NULL);
|
|
||||||
|
|
||||||
builder->b_graph = mie_select_graph_create(builder->b_ctx);
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_builder_get_const(
|
|
||||||
struct mie_select_builder *builder, long long value,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
const struct mie_target *builtin = mie_target_builtin();
|
|
||||||
struct mie_type *ctype = mie_ctx_get_int_type(builder->b_ctx, 32);
|
|
||||||
struct mie_select_node *node = NULL;
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&builder->b_graph->g_nodes);
|
|
||||||
while (entry) {
|
|
||||||
node = b_unbox(struct mie_select_node, entry, n_entry);
|
|
||||||
|
|
||||||
if (node->n_target != builtin) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_opcode != MIE_SELECT_OP_CONSTANT) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(node->n_flags & MIE_SELECT_NODE_F_IVALUE)) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_value.i != value) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_select_node_get_value(node, ctype, 0, out);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
skip:
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
builder->b_graph, builtin, MIE_SELECT_OP_CONSTANT, NULL, 0,
|
|
||||||
&ctype, 1, &node);
|
|
||||||
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->n_flags |= MIE_SELECT_NODE_F_IVALUE;
|
|
||||||
node->n_value.i = value;
|
|
||||||
|
|
||||||
mie_select_node_get_value(node, ctype, 0, out);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_builder_push_instr(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
const struct select_instr_type *i_type
|
|
||||||
= select_type_for_instr(instr->i_type);
|
|
||||||
if (!i_type) {
|
|
||||||
return MIE_ERR_INVALID_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i_type->i_push(builder, instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status get_const_node(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
struct mie_const *c = (struct mie_const *)ir_val;
|
|
||||||
struct mie_select_node *node;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
builder->b_graph, mie_target_builtin(), MIE_SELECT_OP_CONSTANT,
|
|
||||||
NULL, 0, &c->c_type, 1, &node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->n_flags = MIE_SELECT_NODE_F_PVALUE;
|
|
||||||
node->n_value.v = ir_val;
|
|
||||||
|
|
||||||
mie_select_node_get_value(node, c->c_type, 0, out);
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status get_data_node(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
struct mie_data *data = (struct mie_data *)ir_val;
|
|
||||||
unsigned int opcode = 0;
|
|
||||||
struct mie_type *type = NULL;
|
|
||||||
|
|
||||||
switch (data->d_type) {
|
|
||||||
case MIE_DATA_EXTERN_GLOBAL:
|
|
||||||
opcode = MIE_SELECT_OP_GLOBAL_ADDRESS;
|
|
||||||
type = mie_ctx_get_type(builder->b_ctx, MIE_TYPE_PTR);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return MIE_ERR_INVALID_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_node *node;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
builder->b_graph, mie_target_builtin(), opcode, NULL, 0, &type,
|
|
||||||
1, &node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->n_flags = MIE_SELECT_NODE_F_PVALUE;
|
|
||||||
node->n_value.v = ir_val;
|
|
||||||
|
|
||||||
mie_select_node_get_value(node, type, 0, out);
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status get_external_value_node(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
struct mie_type *type = mie_value_get_type(ir_val, builder->b_ctx);
|
|
||||||
|
|
||||||
if (!type) {
|
|
||||||
return MIE_ERR_INVALID_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_node *node;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
builder->b_graph, mie_target_builtin(), MIE_SELECT_OP_REGISTER,
|
|
||||||
NULL, 0, &type, 1, &node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->n_flags = MIE_SELECT_NODE_F_PVALUE;
|
|
||||||
node->n_value.v = ir_val;
|
|
||||||
|
|
||||||
mie_select_node_get_value(node, type, 0, out);
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *mie_select_builder_get_value(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val)
|
|
||||||
{
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
|
|
||||||
.key_data = ir_val,
|
|
||||||
.key_size = sizeof(struct mie_value *),
|
|
||||||
};
|
|
||||||
|
|
||||||
const b_hashmap_value *val = b_hashmap_get(builder->b_nodes, &key);
|
|
||||||
if (val) {
|
|
||||||
return val->value_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *select_val = malloc(sizeof *select_val);
|
|
||||||
if (!select_val) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status status = MIE_ERR_INVALID_VALUE;
|
|
||||||
|
|
||||||
switch (ir_val->v_type->t_id) {
|
|
||||||
case MIE_VALUE_CONST:
|
|
||||||
status = get_const_node(builder, ir_val, select_val);
|
|
||||||
break;
|
|
||||||
case MIE_VALUE_DATA:
|
|
||||||
status = get_data_node(builder, ir_val, select_val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
status = get_external_value_node(builder, ir_val, select_val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
key.key_data = ir_val;
|
|
||||||
key.key_size = sizeof(struct mie_value *);
|
|
||||||
|
|
||||||
b_hashmap_value hashmap_val = {
|
|
||||||
.value_data = select_val,
|
|
||||||
.value_size = sizeof *select_val,
|
|
||||||
};
|
|
||||||
b_hashmap_put(builder->b_nodes, &key, &hashmap_val);
|
|
||||||
|
|
||||||
return select_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_builder_set_value(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *graph_val)
|
|
||||||
{
|
|
||||||
struct mie_select_value *graph_val2 = malloc(sizeof *graph_val2);
|
|
||||||
if (!graph_val2) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(graph_val2, graph_val, sizeof *graph_val);
|
|
||||||
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
|
|
||||||
.key_data = ir_val,
|
|
||||||
.key_size = sizeof(struct mie_value *),
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_value hashmap_val = {
|
|
||||||
.value_data = graph_val2,
|
|
||||||
.value_size = sizeof *graph_val2,
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_put(builder->b_nodes, &key, &hashmap_val);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *mie_select_builder_get_mem_access(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val)
|
|
||||||
{
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
|
|
||||||
.key_data = ir_val,
|
|
||||||
.key_size = sizeof(struct mie_value *),
|
|
||||||
};
|
|
||||||
|
|
||||||
const b_hashmap_value *val = b_hashmap_get(builder->b_mem_access, &key);
|
|
||||||
if (val) {
|
|
||||||
return val->value_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_builder_set_mem_access(
|
|
||||||
struct mie_select_builder *builder, struct mie_value *ir_val,
|
|
||||||
struct mie_select_value *graph_val)
|
|
||||||
{
|
|
||||||
struct mie_select_value *graph_val2 = malloc(sizeof *graph_val2);
|
|
||||||
if (!graph_val2) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(graph_val2, graph_val, sizeof *graph_val);
|
|
||||||
|
|
||||||
b_hashmap_key key = {
|
|
||||||
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
|
|
||||||
.key_data = ir_val,
|
|
||||||
.key_size = sizeof(struct mie_value *),
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_value hashmap_val = {
|
|
||||||
.value_data = graph_val2,
|
|
||||||
.value_size = sizeof *graph_val2,
|
|
||||||
};
|
|
||||||
|
|
||||||
b_hashmap_put(builder->b_mem_access, &key, &hashmap_val);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_builder_collapse_chain_ends(
|
|
||||||
struct mie_select_builder *builder, struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
size_t nr_chains = b_queue_length(&builder->b_graph->g_chain_ends);
|
|
||||||
b_queue_entry *entry = NULL;
|
|
||||||
struct mie_select_chain_end *end = NULL;
|
|
||||||
|
|
||||||
switch (nr_chains) {
|
|
||||||
case 0:
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
case 1:
|
|
||||||
entry = b_queue_first(&builder->b_graph->g_chain_ends);
|
|
||||||
end = b_unbox(struct mie_select_chain_end, entry, c_entry);
|
|
||||||
memcpy(out, end, sizeof *out);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_type *chain_type
|
|
||||||
= mie_ctx_get_type(builder->b_ctx, MIE_TYPE_OTHER);
|
|
||||||
|
|
||||||
struct mie_select_value **operands = calloc(nr_chains, sizeof *operands);
|
|
||||||
if (!operands) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&builder->b_graph->g_chain_ends);
|
|
||||||
size_t i = 0;
|
|
||||||
while (entry) {
|
|
||||||
end = b_unbox(struct mie_select_chain_end, entry, c_entry);
|
|
||||||
operands[i++] = &end->c_value;
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_node *group = NULL;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
builder->b_graph, mie_target_builtin(), MIE_SELECT_OP_CHAIN_GROUP,
|
|
||||||
operands, nr_chains, &chain_type, 1, &group);
|
|
||||||
free(operands);
|
|
||||||
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&builder->b_graph->g_chain_ends);
|
|
||||||
while (entry) {
|
|
||||||
end = b_unbox(struct mie_select_chain_end, entry, c_entry);
|
|
||||||
b_queue_entry *next = b_queue_next(entry);
|
|
||||||
|
|
||||||
b_queue_delete(&builder->b_graph->g_chain_ends, entry);
|
|
||||||
free(end);
|
|
||||||
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_chain_end *group_end = malloc(sizeof *group_end);
|
|
||||||
if (!group_end) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(group_end, 0x0, sizeof *group_end);
|
|
||||||
|
|
||||||
mie_select_node_get_value(group, chain_type, 0, &group_end->c_value);
|
|
||||||
b_queue_push_back(&builder->b_graph->g_chain_ends, &group_end->c_entry);
|
|
||||||
*out = group_end->c_value;
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_node *mie_select_builder_find_node_with_ivalue(
|
|
||||||
struct mie_select_builder *builder, const struct mie_target *target,
|
|
||||||
unsigned int opcode, long long val)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&builder->b_graph->g_nodes);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_select_node *node
|
|
||||||
= b_unbox(struct mie_select_node, entry, n_entry);
|
|
||||||
|
|
||||||
if (node->n_target == target && node->n_opcode == opcode
|
|
||||||
&& node->n_value.i == val) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#ifndef _SELECT_BUILDER_H_
|
|
||||||
#define _SELECT_BUILDER_H_
|
|
||||||
|
|
||||||
#include <mie/ir/instr.h>
|
|
||||||
#include <mie/select/builder.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
#include <mie/select/opcode.h>
|
|
||||||
#include <mie/status.h>
|
|
||||||
|
|
||||||
struct mie_select_value;
|
|
||||||
struct mie_select_builder;
|
|
||||||
|
|
||||||
struct select_instr_type {
|
|
||||||
enum mie_status (*i_push)(struct mie_select_builder *, struct mie_instr *);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct select_node_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct select_instr_type *select_type_for_instr(
|
|
||||||
enum mie_instr_type instr);
|
|
||||||
extern const struct select_node_type *select_type_for_node(
|
|
||||||
enum mie_select_opcode node);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,292 +0,0 @@
|
|||||||
#include <blue/io/file.h>
|
|
||||||
#include <blue/io/path.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <mie/ir/const.h>
|
|
||||||
#include <mie/ir/value.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
#include <mie/target/select.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static b_status write_operand_const(struct mie_value *value, b_stream *out)
|
|
||||||
{
|
|
||||||
struct mie_const *c = MIE_CONST(value);
|
|
||||||
|
|
||||||
switch (c->c_type->t_id) {
|
|
||||||
case MIE_TYPE_INT: {
|
|
||||||
struct mie_int *v = MIE_INT(c);
|
|
||||||
b_stream_write_fmt(out, NULL, "%" PRId64, v->i_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_PTR:
|
|
||||||
case MIE_TYPE_ID:
|
|
||||||
b_stream_write_fmt(out, NULL, "%%%s", value->v_name.n_str);
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_STR: {
|
|
||||||
struct mie_string *v = MIE_STRING(c);
|
|
||||||
|
|
||||||
b_stream_write_fmt(out, NULL, "\"%s\"", v->s_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_ATOM: {
|
|
||||||
struct mie_atom *v = MIE_ATOM(c);
|
|
||||||
|
|
||||||
b_stream_write_fmt(out, NULL, "\"%s\"", v->a_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_SELECTOR: {
|
|
||||||
struct mie_selector *v = MIE_SELECTOR(c);
|
|
||||||
|
|
||||||
b_stream_write_fmt(out, NULL, "\"%s\"", v->sel_value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIE_TYPE_CLASS:
|
|
||||||
b_stream_write_fmt(out, NULL, "@%s", value->v_name.n_str);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_operand(struct mie_value *value, b_stream *out)
|
|
||||||
{
|
|
||||||
if (!value) {
|
|
||||||
b_stream_write_fmt(out, NULL, "null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (value->v_type->t_id) {
|
|
||||||
case MIE_VALUE_CONST:
|
|
||||||
write_operand_const(value, out);
|
|
||||||
break;
|
|
||||||
case MIE_VALUE_INSTR:
|
|
||||||
case MIE_VALUE_BLOCK:
|
|
||||||
case MIE_VALUE_ARG:
|
|
||||||
b_stream_write_fmt(out, NULL, "%%%s", value->v_name.n_str);
|
|
||||||
break;
|
|
||||||
case MIE_VALUE_DATA:
|
|
||||||
case MIE_VALUE_FUNC:
|
|
||||||
b_stream_write_fmt(out, NULL, "@%s", value->v_name.n_str);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
b_stream_write_fmt(
|
|
||||||
out, NULL, "unknown-value:%d", value->v_type->t_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void node_dump_text(struct mie_select_node *node)
|
|
||||||
{
|
|
||||||
printf("N%zu: ", node->n_id);
|
|
||||||
char tmp[128];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < node->n_nr_results; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_results[i]->t_id == MIE_TYPE_OTHER) {
|
|
||||||
printf("ch");
|
|
||||||
} else {
|
|
||||||
mie_type_to_string(node->n_results[i], tmp, sizeof tmp);
|
|
||||||
printf("%s", tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_nr_results > 0) {
|
|
||||||
printf(" = ");
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_target_select_node_name(node->n_target, node->n_opcode, tmp, sizeof tmp);
|
|
||||||
printf("%s", tmp);
|
|
||||||
|
|
||||||
if (node->n_description) {
|
|
||||||
printf(" %s", node->n_description);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
|
|
||||||
printf("<");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & MIE_SELECT_NODE_F_IVALUE) {
|
|
||||||
printf("%lld", node->n_value.i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((node->n_flags & MIE_SELECT_NODE_F_IVALUE)
|
|
||||||
&& (node->n_flags & MIE_SELECT_NODE_F_PVALUE)) {
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & MIE_SELECT_NODE_F_PVALUE) {
|
|
||||||
write_operand(node->n_value.v, b_stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
|
|
||||||
printf(">");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_nr_operands) {
|
|
||||||
printf("(");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < node->n_nr_operands; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
printf(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_select_value *value = &node->n_operands[i].u_value;
|
|
||||||
printf("N%zu:%u", value->v_node->n_id, value->v_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_nr_operands) {
|
|
||||||
printf(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void node_dump_dot(struct mie_select_node *node, b_stream *out)
|
|
||||||
{
|
|
||||||
b_stream_write_fmt(out, NULL, "\tN%zu [label=\"{", node->n_id);
|
|
||||||
|
|
||||||
if (node->n_nr_operands > 0) {
|
|
||||||
b_stream_write_string(out, "{", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < node->n_nr_operands; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
b_stream_write_string(out, "|", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_stream_write_fmt(out, NULL, "<in%zu> %zu", i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_nr_operands > 0) {
|
|
||||||
b_stream_write_string(out, "}|", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
char tmp[256];
|
|
||||||
mie_target_select_node_name(node->n_target, node->n_opcode, tmp, sizeof tmp);
|
|
||||||
b_stream_write_fmt(out, NULL, "<Name> %s", tmp);
|
|
||||||
|
|
||||||
if (node->n_description) {
|
|
||||||
b_stream_write_fmt(out, NULL, " %s", node->n_description);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
|
|
||||||
b_stream_write_string(out, "\\<", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & MIE_SELECT_NODE_F_IVALUE) {
|
|
||||||
b_stream_write_fmt(out, NULL, "%lld", node->n_value.i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((node->n_flags & MIE_SELECT_NODE_F_IVALUE)
|
|
||||||
&& (node->n_flags & MIE_SELECT_NODE_F_PVALUE)) {
|
|
||||||
b_stream_write_string(out, ",", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & MIE_SELECT_NODE_F_PVALUE) {
|
|
||||||
write_operand(node->n_value.v, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
|
|
||||||
b_stream_write_string(out, "\\>", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_stream_write_fmt(out, NULL, "|{N%zu}", node->n_id);
|
|
||||||
|
|
||||||
if (node->n_nr_results > 0) {
|
|
||||||
b_stream_write_string(out, "|{", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < node->n_nr_results; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
b_stream_write_string(out, "|", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_stream_write_fmt(out, NULL, "<out%zu> ", i, i);
|
|
||||||
|
|
||||||
if (node->n_results[i]->t_id == MIE_TYPE_OTHER) {
|
|
||||||
b_stream_write_string(out, "ch", NULL);
|
|
||||||
} else {
|
|
||||||
mie_type_to_string(node->n_results[i], tmp, sizeof tmp);
|
|
||||||
b_stream_write_string(out, tmp, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_nr_results > 0) {
|
|
||||||
b_stream_write_string(out, "}", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_stream_write_string(out, "}\"];\n", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void node_links_dump_dot(struct mie_select_node *node, b_stream *out)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < node->n_nr_operands; i++) {
|
|
||||||
struct mie_select_use *use = &node->n_operands[i];
|
|
||||||
b_stream_write_fmt(
|
|
||||||
out, NULL, "\tN%zu:in%zu -> N%zu:out%zu", node->n_id, i,
|
|
||||||
use->u_value.v_node->n_id, use->u_value.v_index);
|
|
||||||
|
|
||||||
if (use->u_value.v_node->n_results[use->u_value.v_index]->t_id
|
|
||||||
== MIE_TYPE_OTHER) {
|
|
||||||
b_stream_write_string(
|
|
||||||
out, "[style=dashed,color=blue]", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_stream_write_string(out, ";\n", NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_graph_dump_text(struct mie_select_graph *graph)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&graph->g_nodes);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_select_node *node
|
|
||||||
= b_unbox(struct mie_select_node, entry, n_entry);
|
|
||||||
node_dump_text(node);
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_graph_dump_dot(struct mie_select_graph *graph, const char *filename)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(filename, "w");
|
|
||||||
|
|
||||||
b_stream *tmpstream = b_stream_open_fp(fp);
|
|
||||||
|
|
||||||
b_stream_write_string(tmpstream, "digraph G {\n", NULL);
|
|
||||||
b_stream_write_string(tmpstream, "\tnode [shape=Mrecord];\n", NULL);
|
|
||||||
b_stream_write_string(tmpstream, "\trankdir=\"BT\";\n", NULL);
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&graph->g_nodes);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_select_node *node
|
|
||||||
= b_unbox(struct mie_select_node, entry, n_entry);
|
|
||||||
node_dump_dot(node, tmpstream);
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_first(&graph->g_nodes);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_select_node *node
|
|
||||||
= b_unbox(struct mie_select_node, entry, n_entry);
|
|
||||||
node_links_dump_dot(node, tmpstream);
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
b_stream_write_string(tmpstream, "}\n", NULL);
|
|
||||||
|
|
||||||
b_stream_unref(tmpstream);
|
|
||||||
|
|
||||||
char cmd[256];
|
|
||||||
snprintf(cmd, sizeof cmd, "open %s", filename);
|
|
||||||
system(cmd);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
#include <mie/select/opcode.h>
|
|
||||||
#include <mie/status.h>
|
|
||||||
#include <mie/target/target.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct mie_select_graph *mie_select_graph_create(struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct mie_select_graph *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
enum mie_status status = MIE_SUCCESS;
|
|
||||||
struct mie_select_node *entry;
|
|
||||||
|
|
||||||
struct mie_type *entry_values[] = {
|
|
||||||
mie_ctx_get_type(ctx, MIE_TYPE_OTHER),
|
|
||||||
mie_ctx_get_type(ctx, MIE_TYPE_GLUE),
|
|
||||||
};
|
|
||||||
const size_t nr_entry_values
|
|
||||||
= sizeof entry_values / sizeof entry_values[0];
|
|
||||||
|
|
||||||
status = mie_select_graph_get_node(
|
|
||||||
out, mie_target_builtin(), MIE_SELECT_OP_ENTRY, NULL, 0,
|
|
||||||
entry_values, nr_entry_values, &entry);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_select_node_get_value(entry, entry_values[0], 0, &out->g_entry);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_graph_destroy(struct mie_select_graph *graph)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&graph->g_nodes);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_select_node *node
|
|
||||||
= b_unbox(struct mie_select_node, entry, n_entry);
|
|
||||||
b_queue_entry *next = b_queue_next(entry);
|
|
||||||
b_queue_delete(&graph->g_nodes, entry);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (node->n_value) {
|
|
||||||
mie_value_destroy(node->n_value);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(node);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status update_chain_ends(
|
|
||||||
struct mie_select_graph *graph, struct mie_select_value *new_chain)
|
|
||||||
{
|
|
||||||
struct mie_select_node *new_node = new_chain->v_node;
|
|
||||||
|
|
||||||
b_queue_entry *entry = b_queue_first(&graph->g_chain_ends);
|
|
||||||
while (entry) {
|
|
||||||
struct mie_select_chain_end *end
|
|
||||||
= b_unbox(struct mie_select_chain_end, entry, c_entry);
|
|
||||||
struct mie_select_node *value_node = end->c_value.v_node;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < new_node->n_nr_operands; i++) {
|
|
||||||
struct mie_select_node *operand_node
|
|
||||||
= new_node->n_operands[i].u_value.v_node;
|
|
||||||
|
|
||||||
if (value_node == operand_node) {
|
|
||||||
memcpy(&end->c_value, new_chain, sizeof *new_chain);
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_chain_end *end = malloc(sizeof *end);
|
|
||||||
if (!end) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(end, 0x0, sizeof *end);
|
|
||||||
memcpy(&end->c_value, new_chain, sizeof *new_chain);
|
|
||||||
|
|
||||||
b_queue_push_back(&graph->g_chain_ends, &end->c_entry);
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_graph_get_node(
|
|
||||||
struct mie_select_graph *graph, const struct mie_target *target,
|
|
||||||
unsigned int op, struct mie_select_value **operands, size_t nr_operands,
|
|
||||||
struct mie_type **values, size_t nr_values, struct mie_select_node **out)
|
|
||||||
{
|
|
||||||
struct mie_select_node *node = mie_select_node_create(
|
|
||||||
mie_target_builtin(), op, values, nr_values);
|
|
||||||
if (!node) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *operands2
|
|
||||||
= calloc(nr_operands, sizeof *operands2);
|
|
||||||
for (size_t i = 0; i < nr_operands; i++) {
|
|
||||||
assert(operands[i]);
|
|
||||||
memcpy(&operands2[i], operands[i], sizeof *operands2);
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_select_node_set_operands(node, operands2, nr_operands);
|
|
||||||
free(operands2);
|
|
||||||
|
|
||||||
node->n_id = graph->g_node_id++;
|
|
||||||
node->n_target = target;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nr_values; i++) {
|
|
||||||
if (values[i]->t_id != MIE_TYPE_OTHER) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value chain = {
|
|
||||||
.v_node = node,
|
|
||||||
.v_index = i,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mie_status status = update_chain_ends(graph, &chain);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b_queue_push_back(&graph->g_nodes, &node->n_entry);
|
|
||||||
|
|
||||||
*out = node;
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <mie/select/opcode.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define DECLARE_INSTR_TYPE(name) extern struct select_instr_type select_##name
|
|
||||||
#define INSTR_TYPE_ENTRY(op, name) [MIE_INSTR_##op] = &select_##name
|
|
||||||
|
|
||||||
DECLARE_INSTR_TYPE(alloca);
|
|
||||||
DECLARE_INSTR_TYPE(add);
|
|
||||||
DECLARE_INSTR_TYPE(sub);
|
|
||||||
DECLARE_INSTR_TYPE(mul);
|
|
||||||
DECLARE_INSTR_TYPE(div);
|
|
||||||
DECLARE_INSTR_TYPE(cmp_eq);
|
|
||||||
DECLARE_INSTR_TYPE(cmp_neq);
|
|
||||||
DECLARE_INSTR_TYPE(cmp_lt);
|
|
||||||
DECLARE_INSTR_TYPE(cmp_gt);
|
|
||||||
DECLARE_INSTR_TYPE(cmp_leq);
|
|
||||||
DECLARE_INSTR_TYPE(cmp_geq);
|
|
||||||
DECLARE_INSTR_TYPE(load);
|
|
||||||
DECLARE_INSTR_TYPE(store);
|
|
||||||
DECLARE_INSTR_TYPE(msg);
|
|
||||||
DECLARE_INSTR_TYPE(br);
|
|
||||||
DECLARE_INSTR_TYPE(br_if);
|
|
||||||
|
|
||||||
static const struct select_instr_type *instr_types[] = {
|
|
||||||
INSTR_TYPE_ENTRY(ALLOCA, alloca), INSTR_TYPE_ENTRY(LOAD, load),
|
|
||||||
INSTR_TYPE_ENTRY(STORE, store), INSTR_TYPE_ENTRY(MSG, msg),
|
|
||||||
INSTR_TYPE_ENTRY(BR, br), INSTR_TYPE_ENTRY(BR_IF, br_if),
|
|
||||||
INSTR_TYPE_ENTRY(ADD, add), INSTR_TYPE_ENTRY(SUB, sub),
|
|
||||||
INSTR_TYPE_ENTRY(MUL, mul), INSTR_TYPE_ENTRY(DIV, div),
|
|
||||||
INSTR_TYPE_ENTRY(CMP_EQ, cmp_eq), INSTR_TYPE_ENTRY(CMP_NEQ, cmp_neq),
|
|
||||||
INSTR_TYPE_ENTRY(CMP_LT, cmp_lt), INSTR_TYPE_ENTRY(CMP_GT, cmp_gt),
|
|
||||||
INSTR_TYPE_ENTRY(CMP_LEQ, cmp_leq), INSTR_TYPE_ENTRY(CMP_GEQ, cmp_geq),
|
|
||||||
};
|
|
||||||
static const size_t nr_instr_types = sizeof instr_types / sizeof instr_types[0];
|
|
||||||
|
|
||||||
const struct select_instr_type *select_type_for_instr(enum mie_instr_type instr)
|
|
||||||
{
|
|
||||||
if (instr < 0 || instr >= nr_instr_types) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return instr_types[instr];
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/ptr.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/target/select.h>
|
|
||||||
|
|
||||||
static enum mie_status push(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
const struct mie_target *target = mie_select_builder_get_target(builder);
|
|
||||||
struct mie_msg *msg = (struct mie_msg *)instr;
|
|
||||||
|
|
||||||
struct mie_select_value result;
|
|
||||||
enum mie_status status
|
|
||||||
= mie_target_select_lower_msg(target, builder, msg, &result);
|
|
||||||
|
|
||||||
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &result);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct select_instr_type select_msg = {
|
|
||||||
.i_push = push,
|
|
||||||
};
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <blue/core/stringstream.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
#include <mie/select/node.h>
|
|
||||||
#include <mie/select/opcode.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static const struct select_node_type *node_types[] = {
|
|
||||||
|
|
||||||
};
|
|
||||||
static const size_t nr_node_types = sizeof node_types / sizeof node_types[0];
|
|
||||||
|
|
||||||
const struct select_node_type *select_type_for_node(enum mie_select_opcode node)
|
|
||||||
{
|
|
||||||
if (node < 0 || node >= nr_node_types) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node_types[node];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void mie_select_node_iterator_next(struct mie_select_node_iterator *it)
|
|
||||||
{
|
|
||||||
b_queue_iterator_next(&it->it_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mie_select_node_iterator_is_valid(const struct mie_select_node_iterator *it)
|
|
||||||
{
|
|
||||||
return b_queue_iterator_is_valid(&it->it_base);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct mie_select_node *mie_select_node_create(
|
|
||||||
const struct mie_target *target, unsigned int op,
|
|
||||||
struct mie_type **results, size_t nr_results)
|
|
||||||
{
|
|
||||||
struct mie_select_node *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->n_target = target;
|
|
||||||
out->n_opcode = op;
|
|
||||||
out->n_results = calloc(nr_results, sizeof(struct mie_type *));
|
|
||||||
if (!out->n_results) {
|
|
||||||
free(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->n_nr_results = nr_results;
|
|
||||||
memcpy(out->n_results, results, nr_results * sizeof(struct mie_type *));
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_node_destroy(struct mie_select_node *node)
|
|
||||||
{
|
|
||||||
if (node->n_results) {
|
|
||||||
free(node->n_results);
|
|
||||||
}
|
|
||||||
|
|
||||||
mie_select_node_clear_operands(node);
|
|
||||||
|
|
||||||
free(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_node_set_operands(
|
|
||||||
struct mie_select_node *node, struct mie_select_value *operands,
|
|
||||||
size_t nr_operands)
|
|
||||||
{
|
|
||||||
mie_select_node_clear_operands(node);
|
|
||||||
if (!nr_operands) {
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_use *uses = calloc(nr_operands, sizeof *uses);
|
|
||||||
if (!uses) {
|
|
||||||
return MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(uses, 0x0, sizeof *uses);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < nr_operands; i++) {
|
|
||||||
struct mie_select_node *operand_node = operands[i].v_node;
|
|
||||||
|
|
||||||
uses[i].u_user = node;
|
|
||||||
uses[i].u_value = operands[i];
|
|
||||||
|
|
||||||
b_queue_push_back(&operand_node->n_use, &uses[i].u_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
node->n_operands = uses;
|
|
||||||
node->n_nr_operands = nr_operands;
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_node_clear_operands(struct mie_select_node *node)
|
|
||||||
{
|
|
||||||
b_queue_entry *entry = b_queue_first(&node->n_use);
|
|
||||||
while (entry) {
|
|
||||||
|
|
||||||
struct mie_select_use *use
|
|
||||||
= b_unbox(struct mie_select_use, entry, u_entry);
|
|
||||||
if (use->u_value.v_node == node) {
|
|
||||||
memset(&use->u_value, 0x0, sizeof use->u_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = b_queue_next(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->n_operands) {
|
|
||||||
free(node->n_operands);
|
|
||||||
}
|
|
||||||
|
|
||||||
node->n_operands = NULL;
|
|
||||||
node->n_nr_operands = 0;
|
|
||||||
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_node_get_users(
|
|
||||||
struct mie_select_node *node, struct mie_select_node_iterator *it)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_select_node_get_uses(
|
|
||||||
struct mie_select_node *node, struct mie_select_node_iterator *it)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_node_get_value(
|
|
||||||
struct mie_select_node *node, struct mie_type *type, size_t index,
|
|
||||||
struct mie_select_value *out)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < node->n_nr_results; i++) {
|
|
||||||
if (!mie_type_compare(node->n_results[i], type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index > 0) {
|
|
||||||
index--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
out->v_node = node;
|
|
||||||
out->v_index = i;
|
|
||||||
return MIE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
return MIE_ERR_NO_ENTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_select_node_set_description(
|
|
||||||
struct mie_select_node *node, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list arg;
|
|
||||||
va_start(arg, format);
|
|
||||||
b_stringstream *str = b_stringstream_create();
|
|
||||||
b_stream_write_vfmt(str, NULL, format, arg);
|
|
||||||
va_end(arg);
|
|
||||||
|
|
||||||
node->n_description = b_stringstream_steal(str);
|
|
||||||
b_stringstream_unref(str);
|
|
||||||
return node->n_description ? MIE_SUCCESS : MIE_ERR_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_node *mie_select_node_get_glued_node(struct mie_select_node *node)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_node *mie_select_node_get_glued_user(struct mie_select_node *node)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#include <mie/select/node.h>
|
|
||||||
#include <mie/select/opcode.h>
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
#include "builder.h"
|
|
||||||
|
|
||||||
#include <mie/ctx.h>
|
|
||||||
#include <mie/ir/ptr.h>
|
|
||||||
#include <mie/select/graph.h>
|
|
||||||
|
|
||||||
static enum mie_status push_load(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
|
|
||||||
struct mie_load *load = (struct mie_load *)instr;
|
|
||||||
struct mie_type *chain_type = mie_ctx_get_type(
|
|
||||||
mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER);
|
|
||||||
|
|
||||||
struct mie_select_value *chain
|
|
||||||
= mie_select_builder_get_mem_access(builder, load->l_src);
|
|
||||||
if (!chain) {
|
|
||||||
chain = &graph->g_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *operands[] = {
|
|
||||||
chain,
|
|
||||||
mie_select_builder_get_value(builder, load->l_src),
|
|
||||||
};
|
|
||||||
size_t nr_operands = sizeof operands / sizeof operands[0];
|
|
||||||
|
|
||||||
struct mie_type *result[] = {
|
|
||||||
load->l_type,
|
|
||||||
chain_type,
|
|
||||||
};
|
|
||||||
size_t nr_results = sizeof result / sizeof result[0];
|
|
||||||
|
|
||||||
struct mie_select_node *node;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_LOAD, operands,
|
|
||||||
nr_operands, result, nr_results, &node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value value_result, chain_result;
|
|
||||||
mie_select_node_get_value(node, load->l_type, 0, &value_result);
|
|
||||||
mie_select_node_get_value(node, chain_type, 0, &chain_result);
|
|
||||||
|
|
||||||
mie_select_builder_set_mem_access(builder, load->l_src, &chain_result);
|
|
||||||
return mie_select_builder_set_value(
|
|
||||||
builder, MIE_VALUE(instr), &value_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mie_status push_store(
|
|
||||||
struct mie_select_builder *builder, struct mie_instr *instr)
|
|
||||||
{
|
|
||||||
struct mie_store *store = (struct mie_store *)instr;
|
|
||||||
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
|
|
||||||
|
|
||||||
struct mie_select_value *chain
|
|
||||||
= mie_select_builder_get_mem_access(builder, store->s_dest);
|
|
||||||
if (!chain) {
|
|
||||||
chain = &graph->g_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value *operands[] = {
|
|
||||||
chain,
|
|
||||||
mie_select_builder_get_value(builder, store->s_val),
|
|
||||||
mie_select_builder_get_value(builder, store->s_dest),
|
|
||||||
};
|
|
||||||
size_t nr_operands = sizeof operands / sizeof operands[0];
|
|
||||||
|
|
||||||
struct mie_type *result[] = {
|
|
||||||
mie_ctx_get_type(mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER),
|
|
||||||
};
|
|
||||||
size_t nr_results = sizeof result / sizeof result[0];
|
|
||||||
|
|
||||||
struct mie_select_node *node;
|
|
||||||
enum mie_status status = mie_select_graph_get_node(
|
|
||||||
graph, mie_target_builtin(), MIE_SELECT_OP_STORE, operands,
|
|
||||||
nr_operands, result, nr_results, &node);
|
|
||||||
if (status != MIE_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mie_select_value value;
|
|
||||||
mie_select_node_get_value(node, result[0], 0, &value);
|
|
||||||
|
|
||||||
mie_select_builder_set_mem_access(builder, store->s_dest, &value);
|
|
||||||
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct select_instr_type select_load = {
|
|
||||||
.i_push = push_load,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct select_instr_type select_store = {
|
|
||||||
.i_push = push_store,
|
|
||||||
};
|
|
||||||
31
mie/status.c
31
mie/status.c
@@ -1,31 +0,0 @@
|
|||||||
#include <blue/core/error.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <mie/status.h>
|
|
||||||
|
|
||||||
static const b_error_definition error_defs[] = {
|
|
||||||
B_ERROR_DEFINITION(MIE_SUCCESS, "SUCCESS", "Success"),
|
|
||||||
B_ERROR_DEFINITION(MIE_ERR_EOF, "EOF", "Unexpected end of file"),
|
|
||||||
B_ERROR_DEFINITION(MIE_ERR_BAD_SYNTAX, "BAD_SYNTAX", "Invalid syntax"),
|
|
||||||
B_ERROR_DEFINITION(MIE_ERR_NO_MEMORY, "NO_MEMORY", "Out of memory"),
|
|
||||||
B_ERROR_DEFINITION(
|
|
||||||
MIE_ERR_NOT_SUPPORTED, "NOT_SUPPORTED",
|
|
||||||
"Operation not supported"),
|
|
||||||
B_ERROR_DEFINITION(
|
|
||||||
MIE_ERR_INTERNAL_FAILURE, "INTERNAL_FAILURE",
|
|
||||||
"Internal failure"),
|
|
||||||
B_ERROR_DEFINITION(
|
|
||||||
MIE_ERR_INVALID_VALUE, "INVALID_VALUE", "Invalid value"),
|
|
||||||
B_ERROR_DEFINITION(MIE_ERR_NO_ENTRY, "NO_ENTRY", "Name does not exist"),
|
|
||||||
B_ERROR_DEFINITION(MIE_ERR_BAD_FORMAT, "BAD_FORMAT", "Bad format"),
|
|
||||||
};
|
|
||||||
|
|
||||||
static const b_error_vendor error_vendor = {
|
|
||||||
.v_name = "Mie",
|
|
||||||
.v_error_definitions = error_defs,
|
|
||||||
.v_error_definitions_length = sizeof error_defs,
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct b_error_vendor *mie_error_vendor(void)
|
|
||||||
{
|
|
||||||
return &error_vendor;
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#include <mie/select/opcode.h>
|
|
||||||
#include <mie/target/select.h>
|
|
||||||
#include <mie/target/target.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define NODE_NAME(op, name) \
|
|
||||||
case MIE_SELECT_OP_##op: \
|
|
||||||
return snprintf(out, max, name)
|
|
||||||
|
|
||||||
static size_t node_name(
|
|
||||||
const struct mie_target *target, unsigned int opcode, char *out, size_t max)
|
|
||||||
{
|
|
||||||
switch (opcode) {
|
|
||||||
NODE_NAME(ENTRY, "Entry");
|
|
||||||
NODE_NAME(ROOT, "Root");
|
|
||||||
NODE_NAME(BLOCK, "Block");
|
|
||||||
NODE_NAME(CONSTANT, "Constant");
|
|
||||||
NODE_NAME(FRAME_INDEX, "FrameIndex");
|
|
||||||
NODE_NAME(REGISTER, "Register");
|
|
||||||
NODE_NAME(COPY_FROM_REG, "CopyFromReg");
|
|
||||||
NODE_NAME(COPY_TO_REG, "CopyToReg");
|
|
||||||
NODE_NAME(GLOBAL_ADDRESS, "GlobalAddress");
|
|
||||||
NODE_NAME(CHAIN_GROUP, "ChainGroup");
|
|
||||||
NODE_NAME(LOAD, "Load");
|
|
||||||
NODE_NAME(STORE, "Store");
|
|
||||||
NODE_NAME(ADD, "Add");
|
|
||||||
NODE_NAME(SUB, "Sub");
|
|
||||||
NODE_NAME(MUL, "Mul");
|
|
||||||
NODE_NAME(DIV, "Div");
|
|
||||||
NODE_NAME(CMP_EQ, "Cmp.Eq");
|
|
||||||
NODE_NAME(CMP_NEQ, "Cmp.Neq");
|
|
||||||
NODE_NAME(CMP_LT, "Cmp.Lt");
|
|
||||||
NODE_NAME(CMP_GT, "Cmp.Gt");
|
|
||||||
NODE_NAME(CMP_LEQ, "Cmp.Leq");
|
|
||||||
NODE_NAME(CMP_GEQ, "Cmp.Geq");
|
|
||||||
NODE_NAME(XOR, "Xor");
|
|
||||||
NODE_NAME(BR, "Branch");
|
|
||||||
NODE_NAME(BR_COND, "CondBranch");
|
|
||||||
default:
|
|
||||||
return snprintf(out, max, "UNKNOWN");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_target_select_ops __mie_builtin_select_ops = {
|
|
||||||
.s_node_name = node_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t mie_target_select_node_name(
|
|
||||||
const struct mie_target *target, unsigned int opcode, char *out, size_t max)
|
|
||||||
{
|
|
||||||
size_t w = snprintf(out, max, "%s::", target->t_name);
|
|
||||||
|
|
||||||
if (w < max) {
|
|
||||||
max -= w;
|
|
||||||
} else {
|
|
||||||
max = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
out += w;
|
|
||||||
|
|
||||||
if (target->t_select && target->t_select->s_node_name) {
|
|
||||||
w += target->t_select->s_node_name(target, opcode, out, max);
|
|
||||||
} else {
|
|
||||||
w += snprintf(out, max, "%u", opcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_target_select_lower_call(
|
|
||||||
const struct mie_target *target, struct mie_select_builder *builder,
|
|
||||||
struct mie_call *call, struct mie_select_value *result)
|
|
||||||
{
|
|
||||||
if (!target->t_select || !target->t_select->s_lower_call) {
|
|
||||||
return MIE_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return target->t_select->s_lower_call(target, builder, call, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mie_status mie_target_select_lower_msg(
|
|
||||||
const struct mie_target *target, struct mie_select_builder *builder,
|
|
||||||
struct mie_msg *msg, struct mie_select_value *result)
|
|
||||||
{
|
|
||||||
if (!target->t_select || !target->t_select->s_lower_msg) {
|
|
||||||
return MIE_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return target->t_select->s_lower_msg(target, builder, msg, result);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#include <mie/target/target.h>
|
|
||||||
|
|
||||||
const struct mie_target_select_ops __mie_builtin_select_ops;
|
|
||||||
|
|
||||||
static const struct mie_target builtin_target = {
|
|
||||||
.t_name = "Mie",
|
|
||||||
.t_select = &__mie_builtin_select_ops,
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct mie_target *mie_target_builtin(void)
|
|
||||||
{
|
|
||||||
return &builtin_target;
|
|
||||||
}
|
|
||||||
93
mie/type.c
93
mie/type.c
@@ -1,93 +0,0 @@
|
|||||||
#include <mie/type.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
|
|
||||||
{
|
|
||||||
return MIE_TYPE(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mie_value_type type_value_type = {
|
|
||||||
.t_id = MIE_VALUE_TYPE,
|
|
||||||
.t_get_type = get_type,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mie_type *mie_type_create(void)
|
|
||||||
{
|
|
||||||
struct mie_type *out = malloc(sizeof *out);
|
|
||||||
if (!out) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0x0, sizeof *out);
|
|
||||||
|
|
||||||
out->t_base.v_type = &type_value_type;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mie_type_to_string(const struct mie_type *type, char *out, size_t max)
|
|
||||||
{
|
|
||||||
if (!type) {
|
|
||||||
snprintf(out, max, "no-type");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type->t_id) {
|
|
||||||
case MIE_TYPE_PTR:
|
|
||||||
snprintf(out, max, "ptr");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_VOID:
|
|
||||||
snprintf(out, max, "void");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_INT:
|
|
||||||
snprintf(out, max, "i%u", type->t_width);
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_ID:
|
|
||||||
snprintf(out, max, "id");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_STR:
|
|
||||||
snprintf(out, max, "str");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_ATOM:
|
|
||||||
snprintf(out, max, "atom");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_LABEL:
|
|
||||||
snprintf(out, max, "label");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_ARRAY:
|
|
||||||
snprintf(out, max, "array");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_FUNC:
|
|
||||||
snprintf(out, max, "func");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_GLUE:
|
|
||||||
snprintf(out, max, "glue");
|
|
||||||
break;
|
|
||||||
case MIE_TYPE_SELECTOR:
|
|
||||||
snprintf(out, max, "");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snprintf(out, max, "unknown-type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mie_type_compare(const struct mie_type *a, const struct mie_type *b)
|
|
||||||
{
|
|
||||||
if (a->t_id != b->t_id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a->t_count != b->t_count) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a->t_width != b->t_width) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO compare complex types */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user