From 8934bb8e49803790a15b217904bc291e7e6b5c48 Mon Sep 17 00:00:00 2001 From: Matthew Willis Date: Fri, 26 Jun 2009 00:21:54 +0900 Subject: [PATCH] Added type parser, factor llvm type objects, and recursive type resolution --- extra/llvm/core/core.factor | 83 ++++++++++++-- extra/llvm/llvm-tests.factor | 0 extra/llvm/llvm.factor | 0 extra/llvm/types/types-tests.factor | 20 ++++ extra/llvm/types/types.factor | 172 ++++++++++++++++++++++++++++ 5 files changed, 267 insertions(+), 8 deletions(-) delete mode 100644 extra/llvm/llvm-tests.factor delete mode 100644 extra/llvm/llvm.factor create mode 100644 extra/llvm/types/types-tests.factor create mode 100644 extra/llvm/types/types.factor diff --git a/extra/llvm/core/core.factor b/extra/llvm/core/core.factor index 906364efeb..7b0f18bb17 100644 --- a/extra/llvm/core/core.factor +++ b/extra/llvm/core/core.factor @@ -115,6 +115,8 @@ TYPEDEF: void* LLVMModuleProviderRef TYPEDEF: void* LLVMTypeRef +TYPEDEF: void* LLVMTypeHandleRef + TYPEDEF: void* LLVMValueRef TYPEDEF: void* LLVMBasicBlockRef @@ -138,14 +140,79 @@ LLVMCreateModuleProviderForExistingModule ( LLVMModuleRef M ) ; FUNCTION: void LLVMDisposeModuleProvider ( LLVMModuleProviderRef MP ) ; +! Types + +! LLVM types conform to the following hierarchy: +! +! types: +! integer type +! real type +! function type +! sequence types: +! array type +! pointer type +! vector type +! void type +! label type +! opaque type + +! See llvm::LLVMTypeKind::getTypeID. +FUNCTION: LLVMTypeKind LLVMGetTypeKind ( LLVMTypeRef Ty ) ; + +! Operations on integer types +FUNCTION: LLVMTypeRef LLVMInt1Type ( ) ; +FUNCTION: LLVMTypeRef LLVMInt8Type ( ) ; +FUNCTION: LLVMTypeRef LLVMInt16Type ( ) ; +FUNCTION: LLVMTypeRef LLVMInt32Type ( ) ; +FUNCTION: LLVMTypeRef LLVMInt64Type ( ) ; FUNCTION: LLVMTypeRef LLVMIntType ( unsigned NumBits ) ; +FUNCTION: unsigned LLVMGetIntTypeWidth ( LLVMTypeRef IntegerTy ) ; + +! Operations on real types +FUNCTION: LLVMTypeRef LLVMFloatType ( ) ; +FUNCTION: LLVMTypeRef LLVMDoubleType ( ) ; +FUNCTION: LLVMTypeRef LLVMX86FP80Type ( ) ; +FUNCTION: LLVMTypeRef LLVMFP128Type ( ) ; +FUNCTION: LLVMTypeRef LLVMPPCFP128Type ( ) ; +! Operations on function types FUNCTION: LLVMTypeRef -LLVMFunctionType ( LLVMTypeRef ReturnType, - LLVMTypeRef* ParamTypes, - unsigned ParamCount, - int IsVarArg ) ; - +LLVMFunctionType ( LLVMTypeRef ReturnType, LLVMTypeRef* ParamTypes, unsigned ParamCount, int IsVarArg ) ; +FUNCTION: int LLVMIsFunctionVarArg ( LLVMTypeRef FunctionTy ) ; +FUNCTION: LLVMTypeRef LLVMGetReturnType ( LLVMTypeRef FunctionTy ) ; +FUNCTION: unsigned LLVMCountParamTypes ( LLVMTypeRef FunctionTy ) ; +FUNCTION: void LLVMGetParamTypes ( LLVMTypeRef FunctionTy, LLVMTypeRef* Dest ) ; + +! Operations on struct types +FUNCTION: LLVMTypeRef +LLVMStructType ( LLVMTypeRef* ElementTypes, unsigned ElementCount, int Packed ) ; +FUNCTION: unsigned LLVMCountStructElementTypes ( LLVMTypeRef StructTy ) ; +FUNCTION: void LLVMGetStructElementTypes ( LLVMTypeRef StructTy, LLVMTypeRef* Dest ) ; +FUNCTION: int LLVMIsPackedStruct ( LLVMTypeRef StructTy ) ; + +! Operations on array, pointer, and vector types (sequence types) +FUNCTION: LLVMTypeRef LLVMArrayType ( LLVMTypeRef ElementType, unsigned ElementCount ) ; +FUNCTION: LLVMTypeRef LLVMPointerType ( LLVMTypeRef ElementType, unsigned AddressSpace ) ; +FUNCTION: LLVMTypeRef LLVMVectorType ( LLVMTypeRef ElementType, unsigned ElementCount ) ; + +FUNCTION: LLVMTypeRef LLVMGetElementType ( LLVMTypeRef Ty ) ; +FUNCTION: unsigned LLVMGetArrayLength ( LLVMTypeRef ArrayTy ) ; +FUNCTION: unsigned LLVMGetPointerAddressSpace ( LLVMTypeRef PointerTy ) ; +FUNCTION: unsigned LLVMGetVectorSize ( LLVMTypeRef VectorTy ) ; + +! Operations on other types +FUNCTION: LLVMTypeRef LLVMVoidType ( ) ; +FUNCTION: LLVMTypeRef LLVMLabelType ( ) ; +FUNCTION: LLVMTypeRef LLVMOpaqueType ( ) ; + +! Operations on type handles +FUNCTION: LLVMTypeHandleRef LLVMCreateTypeHandle ( LLVMTypeRef PotentiallyAbstractTy ) ; +FUNCTION: void LLVMRefineType ( LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy ) ; +FUNCTION: LLVMTypeRef LLVMResolveTypeHandle ( LLVMTypeHandleRef TypeHandle ) ; +FUNCTION: void LLVMDisposeTypeHandle ( LLVMTypeHandleRef TypeHandle ) ; + +! Types end + FUNCTION: unsigned LLVMCountParams ( LLVMValueRef Fn ) ; FUNCTION: void LLVMGetParams ( LLVMValueRef Fn, LLVMValueRef* Params ) ; @@ -200,7 +267,7 @@ FUNCTION: LLVMValueRef LLVMBuildCondBr FUNCTION: LLVMValueRef LLVMBuildSwitch ( LLVMBuilderRef Builder, LLVMValueRef V, LLVMBasicBlockRef Else, unsigned NumCases ) ; FUNCTION: LLVMValueRef LLVMBuildInvoke -( LLVMBuilderRef Builder, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, +( LLVMBuilderRef Builder, LLVMValueRef Fn, LLVMValueRef* Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, char* Name ) ; FUNCTION: LLVMValueRef LLVMBuildUnwind ( LLVMBuilderRef Builder ) ; @@ -266,7 +333,7 @@ FUNCTION: LLVMValueRef LLVMBuildLoad FUNCTION: LLVMValueRef LLVMBuildStore ( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMValueRef Ptr ) ; FUNCTION: LLVMValueRef LLVMBuildGEP -( LLVMBuilderRef B, LLVMValueRef Pointer, LLVMValueRef *Indices, +( LLVMBuilderRef B, LLVMValueRef Pointer, LLVMValueRef* Indices, unsigned NumIndices, char* Name ) ; ! IB Casts @@ -308,7 +375,7 @@ FUNCTION: LLVMValueRef LLVMBuildFCmp FUNCTION: LLVMValueRef LLVMBuildPhi ( LLVMBuilderRef Builder, LLVMTypeRef Ty, char* Name ) ; FUNCTION: LLVMValueRef LLVMBuildCall -( LLVMBuilderRef Builder, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, char* Name ) ; +( LLVMBuilderRef Builder, LLVMValueRef Fn, LLVMValueRef* Args, unsigned NumArgs, char* Name ) ; FUNCTION: LLVMValueRef LLVMBuildSelect ( LLVMBuilderRef Builder, LLVMValueRef If, LLVMValueRef Then, LLVMValueRef Else, char* Name ) ; FUNCTION: LLVMValueRef LLVMBuildVAArg diff --git a/extra/llvm/llvm-tests.factor b/extra/llvm/llvm-tests.factor deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/extra/llvm/llvm.factor b/extra/llvm/llvm.factor deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/extra/llvm/types/types-tests.factor b/extra/llvm/types/types-tests.factor new file mode 100644 index 0000000000..8e9b9e2037 --- /dev/null +++ b/extra/llvm/types/types-tests.factor @@ -0,0 +1,20 @@ +USING: kernel llvm.types sequences tools.test ; + +[ T{ integer f 32 } ] [ " i32 " parse-type ] unit-test +[ float ] [ " float " parse-type ] unit-test +[ T{ pointer f f x86_fp80 } ] [ " x86_fp80 * " parse-type ] unit-test +[ T{ vector f f 4 T{ integer f 32 } } ] [ " < 4 x i32 > " parse-type ] unit-test +[ T{ struct f f { float double } f } ] [ TYPE: { float , double } ; ] unit-test +[ T{ array f f 0 float } ] [ TYPE: [ 0 x float ] ; ] unit-test + +[ label void metadata ] +[ [ " label " " void " " metadata " ] [ parse-type ] each ] unit-test + +[ T{ function f f float { float float } t } ] +[ TYPE: float ( float , float , ... ) ; ] unit-test + +[ T{ struct f f { float TYPE: i32 (i32)* ; } t } ] +[ TYPE: < { float, i32 (i32)* } > ; ] unit-test + +[ t ] [ TYPE: i32 ; TYPE: i32 ; [ >tref ] bi@ = ] unit-test +[ t ] [ TYPE: i32 * ; TYPE: i32 * ; [ >tref ] bi@ = ] unit-test \ No newline at end of file diff --git a/extra/llvm/types/types.factor b/extra/llvm/types/types.factor new file mode 100644 index 0000000000..91210af83d --- /dev/null +++ b/extra/llvm/types/types.factor @@ -0,0 +1,172 @@ +USING: accessors arrays combinators kernel llvm.core +locals math.parser math multiline +namespaces parser peg.ebnf sequences +sequences.deep specialized-arrays.alien strings vocabs words ; + +IN: llvm.types + +! Type resolution strategy: +! pass 1: +! create the type with uprefs mapped to opaque types +! cache typerefs in enclosing types for pass 2 +! if our type is concrete, then we are done +! +! pass 2: +! wrap our abstract type in a type handle +! create a second type, using the cached enclosing type info +! resolve the first type to the second +! +GENERIC: (>tref) ( type -- LLVMTypeRef ) + +GENERIC: llvm> ( LLVMTypeRef -- type ) + +TUPLE: integer size ; +C: integer + +M: integer (>tref) size>> LLVMIntType ; + +SINGLETONS: float double x86_fp80 fp128 ppc_fp128 ; + +M: float (>tref) drop LLVMFloatType ; +M: double (>tref) drop LLVMDoubleType ; +M: x86_fp80 (>tref) drop LLVMX86FP80Type ; +M: fp128 (>tref) drop LLVMFP128Type ; +M: ppc_fp128 (>tref) drop LLVMPPCFP128Type ; + +SINGLETONS: label void metadata ; + +M: label (>tref) drop LLVMLabelType ; +M: void (>tref) drop LLVMVoidType ; +M: metadata (>tref) drop + "metadata types unsupported by llvm c bindings" throw ; + +! enclosing types cache their llvm refs during +! the first pass, used in the second pass to +! resolve uprefs +TUPLE: enclosing cached ; + +GENERIC: clean ( type -- ) +GENERIC: clean* ( type -- ) +M: object clean drop ; +M: enclosing clean f >>cached clean* ; + +! builds the stack of types that uprefs need to refer to +SYMBOL: types +:: push-type ( type quot: ( type -- LLVMTypeRef ) -- LLVMTypeRef ) + type types get push + type quot call( type -- LLVMTypeRef ) + types get pop over >>cached drop ; + +GENERIC: (>tref)* ( type -- LLVMTypeRef ) +M: enclosing (>tref) [ (>tref)* ] push-type ; + +TUPLE: pointer < enclosing type ; +: ( t -- o ) pointer new swap >>type ; + +M: pointer (>tref)* type>> (>tref) 0 LLVMPointerType ; +M: pointer clean* type>> clean ; + +TUPLE: vector < enclosing size type ; +: ( s t -- o ) + vector new + swap >>type swap >>size ; + +M: vector (>tref)* [ type>> (>tref) ] [ size>> ] bi LLVMVectorType ; +M: vector clean* type>> clean ; + +TUPLE: struct < enclosing types packed? ; +: ( ts p? -- o ) + struct new + swap >>packed? swap >>types ; + +M: struct (>tref)* + [ types>> [ (>tref) ] map >void*-array ] + [ types>> length ] + [ packed?>> 1 0 ? ] tri LLVMStructType ; +M: struct clean* types>> [ clean ] each ; + +TUPLE: array < enclosing size type ; +: ( s t -- o ) + array new + swap >>type swap >>size ; + +M: array (>tref)* [ type>> (>tref) ] [ size>> ] bi LLVMArrayType ; +M: array clean* type>> clean ; + +SYMBOL: ... +TUPLE: function < enclosing return params vararg? ; +: ( ret params var? -- o ) + function new + swap >>vararg? swap >>params swap >>return ; + +M: function (>tref)* { + [ return>> (>tref) ] + [ params>> [ (>tref) ] map >void*-array ] + [ params>> length ] + [ vararg?>> 1 0 ? ] +} cleave LLVMFunctionType ; +M: function clean* [ return>> clean ] [ params>> [ clean ] each ] bi ; + +TUPLE: up-ref height ; +C: up-ref + +M: up-ref (>tref) + types get length swap height>> - types get nth + cached>> [ LLVMOpaqueType ] unless* ; + +: resolve-types ( typeref typeref -- typeref ) + over LLVMCreateTypeHandle [ LLVMRefineType ] dip + [ LLVMResolveTypeHandle ] keep LLVMDisposeTypeHandle ; + +: >tref-caching ( type -- LLVMTypeRef ) + V{ } clone types [ (>tref) ] with-variable ; + +: >tref ( type -- LLVMTypeRef ) + [ >tref-caching ] [ >tref-caching ] [ clean ] tri + 2dup = [ drop ] [ resolve-types ] if ; + +: t. ( type -- ) + >tref + "type-info" LLVMModuleCreateWithName + [ "t" rot LLVMAddTypeName drop ] + [ LLVMDumpModule ] + [ LLVMDisposeModule ] tri ; + +EBNF: parse-type + +WhiteSpace = " "* + +Zero = "0" => [[ drop 0 ]] +LeadingDigit = [1-9] +DecimalDigit = [0-9] +Number = LeadingDigit:d (DecimalDigit)*:ds => [[ ds d prefix string>number ]] +WhiteNumberSpace = WhiteSpace Number:n WhiteSpace => [[ n ]] +WhiteZeroSpace = WhiteSpace (Zero | Number):n WhiteSpace => [[ n ]] + +Integer = "i" Number:n => [[ n ]] +FloatingPoint = ( "float" | "double" | "x86_fp80" | "fp128" | "ppc_fp128" ) => [[ "llvm.types" vocab lookup ]] +LabelVoidMetadata = ( "label" | "void" | "metadata" ) => [[ "llvm.types" vocab lookup ]] +Primitive = LabelVoidMetadata | FloatingPoint +Pointer = T:t WhiteSpace "*" => [[ t ]] +Vector = "<" WhiteNumberSpace:n "x" Type:t ">" => [[ n t ]] +StructureTypesList = "," Type:t => [[ t ]] +Structure = "{" Type:t (StructureTypesList)*:ts "}" => [[ ts t prefix >array f ]] +Array = "[" WhiteZeroSpace:n "x" Type:t "]" => [[ n t ]] +NoFunctionParams = "(" WhiteSpace ")" => [[ drop { } ]] +VarArgs = WhiteSpace "..." WhiteSpace => [[ drop ... ]] +ParamListContinued = "," (Type | VarArgs):t => [[ t ]] +ParamList = "(" Type:t (ParamListContinued*):ts ")" => [[ ts t prefix ]] +Function = T:t WhiteSpace ( ParamList | NoFunctionParams ):ts => [[ ... ts member? dup [ ... ts delete ] when t ts >array rot ]] +PackedStructure = "<" WhiteSpace "{" Type:ty (StructureTypesList)*:ts "}" WhiteSpace ">" => [[ ts ty prefix >array t ]] +UpReference = "\\" Number:n => [[ n ]] +Name = '%' ([a-zA-Z][a-zA-Z0-9]*):id => [[ id flatten >string ]] + +T = Pointer | Function | Primitive | Integer | Vector | Structure | PackedStructure | Array | UpReference | Name + +Type = WhiteSpace T:t WhiteSpace => [[ t ]] + +Program = Type + +;EBNF + +SYNTAX: TYPE: ";" parse-multiline-string parse-type parsed ; \ No newline at end of file -- 2.34.1