From 8c28cc5aaeeb3546e4c113734e18285699bf779e Mon Sep 17 00:00:00 2001 From: Matthias Benkard Date: Wed, 1 Oct 2008 10:32:17 +0200 Subject: LLVM compiler: Support FUNCTION. --- MLKLLVMCompiler.mm | 68 +++++++++++++++++++++++++++++++++ MLKLexicalContext-MLKLLVMCompilation.h | 1 + MLKLexicalContext-MLKLLVMCompilation.mm | 9 +++++ MLKLexicalContext.h | 5 +++ MLKLexicalContext.m | 26 +++++++++++++ 5 files changed, 109 insertions(+) diff --git a/MLKLLVMCompiler.mm b/MLKLLVMCompiler.mm index 137598e..64b2423 100644 --- a/MLKLLVMCompiler.mm +++ b/MLKLLVMCompiler.mm @@ -1026,3 +1026,71 @@ static Constant VoidPointerTy); } @end + + +@implementation MLKSimpleFunctionForm (MLKLLVMCompilation) +-(Value *) reallyProcessForLLVM +{ + // For global functions, this is easy. For local functions, we need to create + // a new MLKCompiledClosure object. + if ([_context functionIsGlobal:_functionName]) + { + Value *mlklexicalenvironment = [_compiler insertClassLookup:@"MLKLexicalEnvironment"]; + Value *env = [_compiler insertMethodCall:@"globalEnvironment" + onObject:mlklexicalenvironment]; + + LRETAIN (_functionName); // FIXME: release +#ifdef __OBJC_GC__ + // FIXME: proper memory management + if (_functionName && MLKInstanceP (_functionName)) + [[NSGarbageCollector defaultCollector] disableCollectorForPointer:_functionName]; +#endif + + Value *symbolV = builder.CreateIntToPtr (ConstantInt::get(Type::Int64Ty, + (uint64_t)_functionName, + false), + VoidPointerTy); + + vector args; + args.push_back (symbolV); + Value *fun = [_compiler insertMethodCall:@"functionForSymbol:" + onObject:env + withArgumentVector:&args]; + return fun; + } + else + { + Value *functionCell, *functionPtr; + Value *closureDataCell, *closureDataPtr; + Value *closureDataLengthCell, *closureDataLength; + + functionCell = builder.Insert ([_context functionCellValueForSymbol:_head]); + functionPtr = builder.CreateLoad (functionCell); + closureDataCell = builder.Insert ([_context closureDataPointerValueForSymbol:_head]); + closureDataPtr = builder.CreateLoad (closureDataCell); + closureDataLengthCell = builder.Insert ([_context closureDataLengthValueForSymbol:_head]); + closureDataLength = builder.CreateLoad (closureDataLengthCell); + + vector argv; + argv.push_back (builder.CreateBitCast (functionPtr, VoidPointerTy)); + argv.push_back (builder.CreateBitCast (closureDataPtr, VoidPointerTy)); + argv.push_back (builder.CreateBitCast (closureDataLength, VoidPointerTy)); + Value *mlkcompiledclosure = [_compiler + insertClassLookup:@"MLKCompiledClosure"]; + Value *closure = + [_compiler insertMethodCall:@"closureWithCode:data:length:" + onObject:mlkcompiledclosure + withArgumentVector:&argv]; + + return closure; + } +} +@end + + +@implementation MLKLambdaFunctionForm (MLKLLVMCompilation) +-(Value *) reallyProcessForLLVM +{ + return [_lambdaForm processForLLVM]; +} +@end diff --git a/MLKLexicalContext-MLKLLVMCompilation.h b/MLKLexicalContext-MLKLLVMCompilation.h index 3effb63..bbbe3fb 100644 --- a/MLKLexicalContext-MLKLLVMCompilation.h +++ b/MLKLexicalContext-MLKLLVMCompilation.h @@ -39,6 +39,7 @@ extern id MLKDummyUseLLVMLexicalContext; -(BOOL) variableHeapAllocationForSymbol:(id)name; -(Instruction *) functionCellValueForSymbol:(id)name; -(Instruction *) closureDataPointerValueForSymbol:(id)name; +-(Instruction *) closureDataLengthValueForSymbol:(id)name; -(Value *) bindingValueForSymbol:(id)name; -(void) locallySetBindingValue:(Value *)value forSymbol:(id)name; -(void) setBindingValue:(Value *)value forSymbol:(id)name; diff --git a/MLKLexicalContext-MLKLLVMCompilation.mm b/MLKLexicalContext-MLKLLVMCompilation.mm index 37f03f5..2d525a5 100644 --- a/MLKLexicalContext-MLKLLVMCompilation.mm +++ b/MLKLexicalContext-MLKLLVMCompilation.mm @@ -75,6 +75,15 @@ id MLKDummyUseLLVMLexicalContext = nil; PointerType::get(PointerType::get(PointerType::get(Type::Int8Ty, 0), 0), 0))); } +-(Instruction *) closureDataLengthValueForSymbol:(id)name +{ + // The length cell isn't really a void** but an intptr_t*. + return (new IntToPtrInst (ConstantInt::get(Type::Int64Ty, + (uint64_t)[self closureDataLengthForSymbol:name], + false), + PointerType::get(PointerType::get(Type::Int8Ty, 0), 0))); +} + -(Instruction *) globalBindingValueForSymbol:(id)name { return (new IntToPtrInst (ConstantInt::get(Type::Int64Ty, diff --git a/MLKLexicalContext.h b/MLKLexicalContext.h index f8b7a14..0e51f2c 100644 --- a/MLKLexicalContext.h +++ b/MLKLexicalContext.h @@ -22,6 +22,9 @@ #import #import +#include + + @class MLKEnvironment, MLKLexicalEnvironment, MLKSymbol, NSSet, NSMutableDictionary, NSString, MLKCons; @@ -95,6 +98,7 @@ -(BOOL) variableIsLexical:(MLKSymbol *)symbol; -(BOOL) variableIsGlobal:(id)name; -(BOOL) functionIsInline:(MLKSymbol *)symbol; +-(BOOL) functionIsGlobal:(id)name; -(id) propertyForVariable:(id)name key:(id)key; -(void) setDeepProperty:(id)object @@ -111,6 +115,7 @@ -(void *) functionCellForSymbol:(id)name; -(void *) closureDataPointerForSymbol:(id)name; +-(intptr_t *) closureDataLengthForSymbol:(id)name; -(id) bindingForSymbol:(id)name; -(void) dealloc; diff --git a/MLKLexicalContext.m b/MLKLexicalContext.m index acb5b4e..0afc66b 100644 --- a/MLKLexicalContext.m +++ b/MLKLexicalContext.m @@ -297,6 +297,12 @@ static MLKLexicalContext *global_context; || [self contextForVariable:name] == [MLKLexicalContext globalContext]); } +-(BOOL) functionIsGlobal:(id)name +{ + return (![self contextForFunction:name] + || [self contextForFunction:name] == [MLKLexicalContext globalContext]); +} + -(BOOL) functionIsInline:(MLKSymbol *)symbol { if ([_functions containsObject:symbol]) @@ -455,6 +461,26 @@ static MLKLexicalContext *global_context; } } +-(intptr_t *) closureDataLengthForSymbol:(id)name +{ + id prop = [self propertyForFunction:name + key:@"LEXCTX.closure-data-length"]; + + if (!prop) + { + intptr_t *cell = malloc (sizeof(intptr_t)); + prop = [NSValue valueWithPointer:cell]; + [self setDeepProperty:prop + forFunction:name + key:@"LEXCTX.closure-data-length"]; + return cell; + } + else + { + return (intptr_t*)[prop pointerValue]; + } +} + -(id) bindingForSymbol:(id)name { id prop = [self propertyForVariable:name -- cgit v1.2.3