Compare commits

..

5 Commits

93 changed files with 2607 additions and 6300 deletions

View File

@@ -1,6 +1,62 @@
BasedOnStyle: WebKit
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
DerivePointerAlignment: false
PointerAlignment: Right

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "mie"]
path = mie
url = https://g.wash.red/wash/mie.git

7
doc/mie-passes.txt Normal file
View 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
View 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
View 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
}
}

View File

@@ -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
data @StringBuffer = external global id
ivy.package-ref "std.io"
data @.str.0 = str "Received "
data @.str.1 = str ", "
ivy.module {
%cout = ivy.global-ref @cout -> ptr
data @.atom.0 = atom "years"
data @.atom.1 = atom "months"
data @.atom.2 = atom "days"
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
type @_ZN3net9doorstuck4testC6PersonE = class {
id @name,
id @age,
id @val
}
define void @_ZN3net9doorstuck4testC6PersonM4init4name3ageE(id %self, id %0) instance {
entry:
%1 = getelementptr class @_ZN3net9doorstuck4testC6PersonE, id %self, i32 #0
store id %0, ptr %1
%2 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
store id %1, ptr %2
ret void
}
define void @_ZN3net9doorstuck4testC6PersonM4test5param0E(id %0, id %1) instance {
entry:
%2 = load id, ptr @cout
; %4 = StringBuilder new
%3 = load id, ptr @StringBuilder
%4 = msg id %3, @_M3newE
; (void) tempstr append:'Received '
%5 = load id, ptr @.str.0
msg void, id %3, @_M06appendE [id %5]
; (void) tempstr append:data (param 0)
msg void, id %3, @_M06appendE [id %0]
; (void) tempstr append:', '
%6 = load id, ptr @.str.1
msg void, id %3, @_M06appendE [id %6]
; [void] tempstr append:extra (param 1)
msg void, id %3, @_M06appendE [id %1]
; %7 = tempstr toString
%7 = msg id, id %3, @_M8toStringE
; cout put:'Received {data}, {extra}'
msg void, id %2, @_M03put [id %7]
ret void
}
define id @_ZN3net9doorstuck4testC6PersonM4nameE(id %self) instance {
entry:
%0 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #0
%1 = load id, ptr %0
ret id %1
}
define id @_ZN3net9doorstuck4testC6PersonM3ageE(id %self) instance {
entry:
%0 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
%1 = load id, ptr %0
ret id %1
}
define id @_ZN3net9doorstuck4testC6PersonM11ageInMonthsE(id %self, id %0) instance {
entry:
%1 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
%2 = load id, ptr %1
ret id %1
}
define void @_ZN3net9doorstuck4testC6PersonM07setNameE(id %self, id %1) instance {
entry:
%2 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
store id %1, ptr %2
ret void
}
define void @_ZN3net9doorstuck4testC6PersonM06setAge6inUnitE(id %self, i32 %1, id %2) instance {
entry:
%3 = load atom, ptr @.atom.0
%4 = load atom, ptr @.atom.1
%5 = load atom, ptr @.atom.2
switch id %2, label %default [
atom %3, label %years
atom %4, label %months
atom %5, label %days
]
years:
%6 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
store i32 %2, ptr %6
br label %end
months:
%7 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
%8 = div i32 %2, #12
store i32 %8, ptr %7
br label %end
days:
%9 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
%10 = div i32 %2, #365
store i32 %10, ptr %9
br label %end
default:
%11 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #1
store i32 #0, ptr %11
br label %end
end:
ret void
}
define id @_ZN3net9doorstuck4testC6PersonM012getAgeInUnitE(id %0, id %1) instance {
entry:
}
define id @_ZN3net9doorstuck4testC6PersonP15examplePropertyG(id %self) instance {
entry:
%0 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #2
%1 = load id, ptr %0
ret id %1
}
define void @_ZN3net9doorstuck4testC6PersonP15examplePropertyS(id %self, id %0) instance {
entry:
%1 = getelementptr class @_ZN33net9doorstuck4testC6PersonE, id %self, i32 #2
store id %0, ptr %1
ret void
ivy.msgh.object 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.msgh.object test(param:%data, _:%extra) -> void {
%0 = ivy.string-builder.begin
ivy.string-builder.add %0 << "Received "
ivy.string-builder.add %0 << %data : #ivy.id
ivy.string-builder.add %0 << ", "
ivy.string-builder.add %0 << %extra : #ivy.id
%1 = ivy.string-builder.end %0 -> #ivy.id
%2 = ptr.load %cout : ptr -> #ivy.id
ivy.msg.send to %2, put:%1 -> void
func.return : ()
}
ivy.msgh.object name -> #ivy.id {
%0 = ptr.load %self.name : ptr -> #ivy.id
func.return %0 : #ivy.id
}
ivy.msgh.object age -> #ivy.id {
%0 = ptr.load %self.age : ptr -> #ivy.id
func.return %0 : #ivy.id
}
ivy.msgh.object 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.msgh.object set-name:%name -> void {
ptr.store %name, %self.name : #ivy.id, ptr
func.return : ()
}
ivy.msgh.object set-age:%age -> void {
ptr.store %age, %self.age : #ivy.id, ptr
func.return : ()
}
ivy.msgh.object set-age:%age in-units:%units -> void {
scf.switch : () -> void
case {
%0 = ivy.atom "years"
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
scf.switch-condition %cmptmp.0
} then {
ptr.store %age, %self.age : #ivy.id, ptr
scf.switch-break : ()
} case {
%1 = ivy.atom "months"
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
scf.condition %cmptmp.1
} then {
%d0 = i32.constant 12
%divtmp.0 = ivy.div %age, %d0 : (#ivy.id, i32) -> #ivy.id
ptr.store %divtmp.0, %self.age : #ivy.id, ptr
scf.switch-break : ()
} case {
%2 = ivy.atom "days"
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
scf.condition %cmptmp.2
} then {
%d1 = i32.constant 365
%divtmp.1 = ivy.div %age, %d1 : (#ivy.id, i32) -> #ivy.id
ptr.store %divtmp.1, %self.age : #ivy.id, ptr
scf.switch-break : ()
} default {
%d2 = i32.constant 0
scf.switch-break : ()
}
func.return : ()
}
ivy.msgh.object get-age-in-units:%units -> #ivy.id {
%result = scf.switch : () -> #ivy.id
case {
%0 = ivy.atom "years"
%cmptmp.0 = ivy.cmp eq %age, %0 : (#ivy.id, #ivy.atom) -> i1
scf.switch-condition %cmptmp.0
} then {
%v0 = ptr.load %self.age : ptr -> #ivy.id
scf.switch-break %v0 : #ivy.id
} case {
%1 = ivy.atom "months"
%cmptmp.1 = ivy.cmp eq %age, %1 : (#ivy.id, #ivy.atom) -> i1
scf.condition %cmptmp.1
} then {
%v0 = ptr.load %self.age : ptr -> #ivy.id
%d0 = i32.constant 12
%divtmp.0 = ivy.div %v0, %d0 : (#ivy.id, i32) -> #ivy.id
scf.switch-break %divtmp.0 : #ivy.id
} case {
%2 = ivy.atom "days"
%cmptmp.2 = ivy.cmp eq %age, %2 : (#ivy.id, #ivy.atom) -> i1
scf.condition %cmptmp.2
} then {
%v1 = ptr.load %self.age : ptr -> #ivy.id
%d1 = i32.constant 365
%divtmp.1 = ivy.div %v1, %d1 : (#ivy.id, i32) -> #ivy.id
scf.switch-break %divtmp.1 : #ivy.id
} default {
%d2 = i32.constant 0
scf.switch-break %d2 : #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.__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
}
}

View 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 : ()
}
}

View 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 : ()
}
}

View 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 : ()
}
}

View 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 : ()
}
}

View 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 : ()
}
}

View File

@@ -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
}

View File

@@ -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.
x = (((1 + 2 * 3) multiply-by:3) add: 5) + 2.
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.
x = OrderedCollection new
x = Ordered-Collection new
add: 2;
add: 4;
add: 6;
@@ -21,7 +21,7 @@ x = OrderedCollection new
age = Person new(name:"John Doe", age:34)
set-age:144 in-unit:"months";
ageInMonths.
age-in-months.
x = 5.
q = 10 if x > 2 else 20.

View File

@@ -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 {
entry:
%0 = load str, ptr @.str.0
%str = alloca id
store str %0, ptr %str
ivy.for-each %c in %str {
ivy.msg to %cout, -put:%c
}
%1 = load id, ptr %str
%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
ivy.msg to %cout, -put:%.str.0
%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
View 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. */

View File

@@ -48,7 +48,6 @@ class Person
compatibility with lambdas.
**/
- init(name:name age:age)
var x.
self::name = name.
self::age = age!
@@ -80,7 +79,7 @@ class Person
_ => 0
end!
/* Properties are defined using the $ symbol.
/* Properties are defined using the -> symbol.
They accomplish two things:
1) they make it easy to synthesize the -get: and -put:at: messages
that the package dot syntax requires.
@@ -109,7 +108,7 @@ class Person
/* 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 |
-> example-property-2 |
get => [ ^self::val ],
set => [ :x | self::val = x ].
@@ -119,23 +118,23 @@ class Person
If either the `set` or `get` elements are not provided, the property
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,
by setting the getter and setters to default implementations.
The default getter will return the value of a private member variable
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
variable named by prepending two underscores to the property name
(__exampleProperty3 in this case) to the value provided to the setter. */
-> example-property-3 (get, set)
(__example-property-4 in this case) to the value provided to the setter. */
-> example-property-4 (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-4 (get)
-> example-property-5 (get)
end
p1 = Person new(name:'John Doe', age:34).
@@ -151,8 +150,8 @@ while i < 100 do
i += 2
end
for i in 0 to:100 step:2 do
cout put:'Count is {i}'
for x in 0 to:100 step:2 do
cout put:'Count is {x}'
end
/**
@@ -223,11 +222,11 @@ pkg[0] = 16.
/* All of these accesses are equivalent */
pkg['x'] = 32.
pkg->x = 32.
pkg put:32 at:'x'.
pkg at:'x' put:32.
index = 'x'.
pkg[index] = 32.
pkg put:32 at:index.
pkg at:index put:32.
/**
this syntax, and the pkg.* instructions that it translates to, is
@@ -274,7 +273,7 @@ end
following criteria:
a) is an Iterator object; 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)
**/
@@ -311,7 +310,7 @@ end
on:$err:number-format do:[ :err :data |
cout put:'Cannot parse integer string ({err})'
];
onError:[ :err :data |
on-error:[ :err :data |
cout put:'Error {err} occurred ({data})'
];
call.

View File

@@ -1,36 +1,9 @@
y = -1 + 2 * 3 / 4 * 5 - 6 + 7 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).
p = 5 multiply(by:3, add:(2 + 1)).
q = 10 squared squared.
package net.doorstuck.test
p1
set-age:2 squared squared + 4 squared multiply(by:2, add:4 + 1 * 3)
in:"mon" + "ths".
use std.io
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.
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
cout put:'Answer: {x}'

View File

@@ -1,6 +1,6 @@
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 ]

96
doc/sample/Sum.2.mie Normal file
View 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 : ()
}
}
}

View File

@@ -1,4 +1,9 @@
var x = 2 + 3.
var y = x.
var z.
var (x, y) = (3, 4).
x = 3.
y = 0.
if x > 10 then
y = 4
else
y = 2
end

View File

@@ -229,6 +229,9 @@ static b_result generate_mie_ir(struct compile_ctx *ctx)
static b_result build_block_isel_graph(
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);
while (entry) {
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);
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,
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);
}

View File

@@ -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 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 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 /\-[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-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*\n\)\@=/
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 ivyLineContinuation /\\\n/
" 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
" 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
syn match ivyBraces "[{}]" display
syn match ivyBrackets "[[\]]" 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 "=\{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 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 keyword ivyWordOperator is not understands and or
@@ -147,15 +158,14 @@ hi def link ivyStatement Statement
hi def link ivyRepeat Repeat
hi def link ivyConditional Conditional
hi def link ivySelectorLabel Tag
hi def link ivyUnnamedLabel @variable.builtin
hi def link ivyUnnamedVariable @variable.builtin
hi def link ivyUnnamedLabel Comment
hi def link ivyUnnamedVariable Comment
hi def link ivyLambdaParameter @variable.builtin
hi def link ivyException Exception
hi def link ivyParens Delimiter
hi def link ivyBraces Structure
hi def link ivyBrackets Define
hi def link ivyLambdaSymbols Define
hi def link ivyControlSymbols Keyword
hi def link ivyModifier StorageClass
hi def link ivyAccessModifier ivyModifier
@@ -176,6 +186,7 @@ hi def link ivyTypeOf ivyKeywordOperator
hi def link ivyTypeOfOperand Typedef
hi def link ivyTypeOfError Error
hi def link ivyOpSymbols Operator
hi def link ivyPackageAccessOperator Operator
hi def link ivyOtherSymbols Structure
hi def link ivyLogicSymbols Operator
hi def link ivyWordOperator Operator

1
mie Submodule

Submodule mie added at 937dc57c4e

View File

@@ -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})

View File

@@ -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
View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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);
}

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

View File

View File

View File

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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,
};

View File

@@ -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);

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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];
}

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -1,2 +0,0 @@
#include <mie/select/node.h>
#include <mie/select/opcode.h>

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}