1 USING: accessors arrays combinators kernel llvm.core
2 locals math.parser math multiline
3 namespaces parser peg.ebnf sequences
4 sequences.deep specialized-arrays.alien strings vocabs words ;
8 ! Type resolution strategy:
10 ! create the type with uprefs mapped to opaque types
11 ! cache typerefs in enclosing types for pass 2
12 ! if our type is concrete, then we are done
15 ! wrap our abstract type in a type handle
16 ! create a second type, using the cached enclosing type info
17 ! resolve the first type to the second
19 GENERIC: (>tref) ( type -- LLVMTypeRef )
21 GENERIC: llvm> ( LLVMTypeRef -- type )
26 M: integer (>tref) size>> LLVMIntType ;
28 SINGLETONS: float double x86_fp80 fp128 ppc_fp128 ;
30 M: float (>tref) drop LLVMFloatType ;
31 M: double (>tref) drop LLVMDoubleType ;
32 M: x86_fp80 (>tref) drop LLVMX86FP80Type ;
33 M: fp128 (>tref) drop LLVMFP128Type ;
34 M: ppc_fp128 (>tref) drop LLVMPPCFP128Type ;
36 SINGLETONS: label void metadata ;
38 M: label (>tref) drop LLVMLabelType ;
39 M: void (>tref) drop LLVMVoidType ;
40 M: metadata (>tref) drop
41 "metadata types unsupported by llvm c bindings" throw ;
43 ! enclosing types cache their llvm refs during
44 ! the first pass, used in the second pass to
46 TUPLE: enclosing cached ;
48 GENERIC: clean ( type -- )
49 GENERIC: clean* ( type -- )
50 M: object clean drop ;
51 M: enclosing clean f >>cached clean* ;
53 ! builds the stack of types that uprefs need to refer to
55 :: push-type ( type quot: ( type -- LLVMTypeRef ) -- LLVMTypeRef )
57 type quot call( type -- LLVMTypeRef )
58 types get pop over >>cached drop ;
60 GENERIC: (>tref)* ( type -- LLVMTypeRef )
61 M: enclosing (>tref) [ (>tref)* ] push-type ;
63 TUPLE: pointer < enclosing type ;
64 : <pointer> ( t -- o ) pointer new swap >>type ;
66 M: pointer (>tref)* type>> (>tref) 0 LLVMPointerType ;
67 M: pointer clean* type>> clean ;
69 TUPLE: vector < enclosing size type ;
70 : <vector> ( s t -- o )
72 swap >>type swap >>size ;
74 M: vector (>tref)* [ type>> (>tref) ] [ size>> ] bi LLVMVectorType ;
75 M: vector clean* type>> clean ;
77 TUPLE: struct < enclosing types packed? ;
78 : <struct> ( ts p? -- o )
80 swap >>packed? swap >>types ;
83 [ types>> [ (>tref) ] map >void*-array ]
85 [ packed?>> 1 0 ? ] tri LLVMStructType ;
86 M: struct clean* types>> [ clean ] each ;
88 TUPLE: array < enclosing size type ;
89 : <array> ( s t -- o )
91 swap >>type swap >>size ;
93 M: array (>tref)* [ type>> (>tref) ] [ size>> ] bi LLVMArrayType ;
94 M: array clean* type>> clean ;
97 TUPLE: function < enclosing return params vararg? ;
98 : <function> ( ret params var? -- o )
100 swap >>vararg? swap >>params swap >>return ;
102 M: function (>tref)* {
104 [ params>> [ (>tref) ] map >void*-array ]
107 } cleave LLVMFunctionType ;
108 M: function clean* [ return>> clean ] [ params>> [ clean ] each ] bi ;
110 TUPLE: up-ref height ;
114 types get length swap height>> - types get nth
115 cached>> [ LLVMOpaqueType ] unless* ;
117 : resolve-types ( typeref typeref -- typeref )
118 over LLVMCreateTypeHandle [ LLVMRefineType ] dip
119 [ LLVMResolveTypeHandle ] keep LLVMDisposeTypeHandle ;
121 : >tref-caching ( type -- LLVMTypeRef )
122 V{ } clone types [ (>tref) ] with-variable ;
124 : >tref ( type -- LLVMTypeRef )
125 [ >tref-caching ] [ >tref-caching ] [ clean ] tri
126 2dup = [ drop ] [ resolve-types ] if ;
130 "type-info" LLVMModuleCreateWithName
131 [ "t" rot LLVMAddTypeName drop ]
133 [ LLVMDisposeModule ] tri ;
139 Zero = "0" => [[ drop 0 ]]
142 Number = LeadingDigit:d (DecimalDigit)*:ds => [[ ds d prefix string>number ]]
143 WhiteNumberSpace = WhiteSpace Number:n WhiteSpace => [[ n ]]
144 WhiteZeroSpace = WhiteSpace (Zero | Number):n WhiteSpace => [[ n ]]
146 Integer = "i" Number:n => [[ n <integer> ]]
147 FloatingPoint = ( "float" | "double" | "x86_fp80" | "fp128" | "ppc_fp128" ) => [[ "llvm.types" vocab lookup ]]
148 LabelVoidMetadata = ( "label" | "void" | "metadata" ) => [[ "llvm.types" vocab lookup ]]
149 Primitive = LabelVoidMetadata | FloatingPoint
150 Pointer = T:t WhiteSpace "*" => [[ t <pointer> ]]
151 Vector = "<" WhiteNumberSpace:n "x" Type:t ">" => [[ n t <vector> ]]
152 StructureTypesList = "," Type:t => [[ t ]]
153 Structure = "{" Type:t (StructureTypesList)*:ts "}" => [[ ts t prefix >array f <struct> ]]
154 Array = "[" WhiteZeroSpace:n "x" Type:t "]" => [[ n t <array> ]]
155 NoFunctionParams = "(" WhiteSpace ")" => [[ drop { } ]]
156 VarArgs = WhiteSpace "..." WhiteSpace => [[ drop ... ]]
157 ParamListContinued = "," (Type | VarArgs):t => [[ t ]]
158 ParamList = "(" Type:t (ParamListContinued*):ts ")" => [[ ts t prefix ]]
159 Function = T:t WhiteSpace ( ParamList | NoFunctionParams ):ts => [[ ... ts member? dup [ ... ts delete ] when t ts >array rot <function> ]]
160 PackedStructure = "<" WhiteSpace "{" Type:ty (StructureTypesList)*:ts "}" WhiteSpace ">" => [[ ts ty prefix >array t <struct> ]]
161 UpReference = "\\" Number:n => [[ n <up-ref> ]]
162 Name = '%' ([a-zA-Z][a-zA-Z0-9]*):id => [[ id flatten >string ]]
164 T = Pointer | Function | Primitive | Integer | Vector | Structure | PackedStructure | Array | UpReference | Name
166 Type = WhiteSpace T:t WhiteSpace => [[ t ]]
172 SYNTAX: TYPE: ";" parse-multiline-string parse-type parsed ;