From a5364817b1cd751832a4634e4afbd67bb668fa2e Mon Sep 17 00:00:00 2001
From: Matthias Andreas Benkard <matthias@benkard.de>
Date: Mon, 1 Sep 2008 23:39:42 +0200
Subject: LLVM compiler: Add support for heap allocation of lexical variables.

---
 MLKLLVMCompiler.mm                      | 51 +++++++++++++++++++++++++--------
 MLKLexicalContext-MLKLLVMCompilation.h  |  4 ++-
 MLKLexicalContext-MLKLLVMCompilation.mm | 20 +++++++++++--
 MLKLexicalContext.h                     |  2 +-
 MLKLexicalContext.m                     | 12 ++++----
 MLKLexicalEnvironment.m                 | 12 ++++----
 6 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/MLKLLVMCompiler.mm b/MLKLLVMCompiler.mm
index b40d4d0..e0d53dd 100644
--- a/MLKLLVMCompiler.mm
+++ b/MLKLLVMCompiler.mm
@@ -458,10 +458,15 @@ static Constant
                          onObject:dynctx
                          withArgumentVector:&args];
     }
-  else if ([_context variableHeapAllocationForSymbol:_form])
+  else if ([_context contextForVariable:_form] == [MLKLexicalContext globalContext])
     {
       //[_compiler insertTrace:@"Global."];
-      Value *binding = builder.CreateLoad (builder.Insert ([_context bindingCellValueForSymbol:_form]));
+      Value *binding = builder.Insert ([_context globalBindingValueForSymbol:_form]);
+      value = [_compiler insertMethodCall:@"value" onObject:binding];      
+    }
+  else if ([_context variableHeapAllocationForSymbol:_form])
+    {
+      Value *binding = [_context bindingValueForSymbol:_form];
       value = [_compiler insertMethodCall:@"value" onObject:binding];
     }
   else
@@ -693,15 +698,29 @@ static Constant
 
   while ((binding_form = [e nextObject]))
     {
-      // FIXME: Handle heap allocation.
       Value *binding_value = [[binding_form valueForm] processForLLVM];
-      Value *binding_variable = builder.CreateAlloca (PointerTy,
-                                                      NULL,
-                                                      [(MLKPrintToString([binding_form name]))
-                                                        UTF8String]);
-      builder.CreateStore (binding_value, binding_variable);
-      [_bodyContext setValueValue:binding_variable
-                    forSymbol:[binding_form name]];
+
+      if ([_bodyContext variableHeapAllocationForSymbol:[binding_form name]])
+        {
+          Value *mlkbinding = [_compiler insertClassLookup:@"MLKBinding"];
+          std::vector<Value *> args (1, binding_value);
+          Value *binding = [_compiler insertMethodCall:@"bindingWithValue:"
+                                      onObject:mlkbinding
+                                      withArgumentVector:&args];
+          [_bodyContext setBindingValue:binding
+                        forSymbol:[binding_form name]];
+        }
+      else
+        {
+          Value *binding_variable = builder.CreateAlloca (PointerTy,
+                                                          NULL,
+                                                          [(MLKPrintToString([binding_form name]))
+                                                            UTF8String]);
+          builder.CreateStore (binding_value, binding_variable);
+
+          [_bodyContext setValueValue:binding_variable
+                        forSymbol:[binding_form name]];
+        }
     }
 
   e = [_bodyForms objectEnumerator];
@@ -806,10 +825,18 @@ static Constant
                      onObject:dynctx
                      withArgumentVector:&args];          
         }
+      else if ([_context contextForVariable:variable] == [MLKLexicalContext globalContext])
+        {
+          Value *binding = builder.Insert ([_context globalBindingValueForSymbol:variable]);
+          std::vector<Value *> args (1, value);
+
+          [_compiler insertVoidMethodCall:@"setValue:"
+                     onObject:binding
+                     withArgumentVector:&args];
+        }
       else if ([_context variableHeapAllocationForSymbol:variable])
         {
-          Value *binding = builder.CreateLoad (builder.Insert ([_context
-                                                                 bindingCellValueForSymbol:variable]));
+          Value *binding = [_context bindingValueForSymbol:variable];
           std::vector<Value *> args (1, value);
 
           [_compiler insertVoidMethodCall:@"setValue:"
diff --git a/MLKLexicalContext-MLKLLVMCompilation.h b/MLKLexicalContext-MLKLLVMCompilation.h
index 4f4c849..b6fdf9d 100644
--- a/MLKLexicalContext-MLKLLVMCompilation.h
+++ b/MLKLexicalContext-MLKLLVMCompilation.h
@@ -39,7 +39,9 @@ extern id MLKDummyUseLLVMLexicalContext;
 -(BOOL) variableHeapAllocationForSymbol:(id)name;
 -(Instruction *) functionCellValueForSymbol:(id)name;
 -(Instruction *) closureDataPointerValueForSymbol:(id)name;
--(Instruction *) bindingCellValueForSymbol:(id)name;
+-(Value *) bindingValueForSymbol:(id)name; 
+-(void) setBindingValue:(Value *)value forSymbol:(id)name;
+-(Instruction *) globalBindingValueForSymbol:(id)name;
 -(Value *) valueValueForSymbol:(id)name;
 //-(void) setFunctionCellValue:(Value *)cellPtr forSymbol:(id)name;
 //-(void) setClosureDataPointerValue:(Value *)pointer forSymbol:(id)name;
diff --git a/MLKLexicalContext-MLKLLVMCompilation.mm b/MLKLexicalContext-MLKLLVMCompilation.mm
index 45208ed..d3a84b3 100644
--- a/MLKLexicalContext-MLKLLVMCompilation.mm
+++ b/MLKLexicalContext-MLKLLVMCompilation.mm
@@ -76,12 +76,26 @@ id MLKDummyUseLLVMLexicalContext = nil;
                             PointerType::get(PointerType::get(Type::Int8Ty, 0), 0)));
 }
 
--(Instruction *) bindingCellValueForSymbol:(id)name
+-(Instruction *) globalBindingValueForSymbol:(id)name
 {
   return (new IntToPtrInst (ConstantInt::get(Type::Int64Ty,
-                                             (uint64_t)[self bindingCellForSymbol:name],
+                                             (uint64_t)[self bindingForSymbol:name],
                                              false),
-                            PointerType::get(PointerType::get(Type::Int8Ty, 0), 0)));
+                            PointerType::get(Type::Int8Ty, 0)));
+}
+
+-(Value *) bindingValueForSymbol:(id)name
+{
+  return (Value *) [[self deepPropertyForVariable:name
+                          key:@"LLVM.variable-binding"]
+                     pointerValue];
+}
+
+-(void) setBindingValue:(Value *)value forSymbol:(id)name
+{
+  [self setDeepProperty:[NSValue valueWithPointer:value]
+        forVariable:name
+        key:@"LLVM.variable-binding"];
 }
 
 -(Value *) valueValueForSymbol:(id)name
diff --git a/MLKLexicalContext.h b/MLKLexicalContext.h
index 0702704..2368636 100644
--- a/MLKLexicalContext.h
+++ b/MLKLexicalContext.h
@@ -107,7 +107,7 @@
 
 -(void *) functionCellForSymbol:(id)name;
 -(void *) closureDataPointerForSymbol:(id)name;
--(id *) bindingCellForSymbol:(id)name;
+-(id) bindingForSymbol:(id)name;
 
 -(void) dealloc;
 @end
diff --git a/MLKLexicalContext.m b/MLKLexicalContext.m
index 1ffa726..dd0dc9c 100644
--- a/MLKLexicalContext.m
+++ b/MLKLexicalContext.m
@@ -436,24 +436,22 @@ static MLKLexicalContext *global_context;
     }
 }
 
--(id *) bindingCellForSymbol:(id)name
+-(id) bindingForSymbol:(id)name
 {
   id prop = [self deepPropertyForVariable:name
                   key:@"LEXCTX.variable-binding"];
 
   if (!prop)
     {
-      id *cell = malloc (sizeof(id));
-      *cell = [[MLKBinding alloc] init];
-      prop = [NSValue valueWithPointer:cell];
-      [self setDeepProperty:prop
+      id binding = [[MLKBinding alloc] init];
+      [self setDeepProperty:binding
             forVariable:name
             key:@"LEXCTX.variable-binding"];
-      return cell;
+      return binding;
     }
   else
     {
-      return [prop pointerValue];
+      return prop;
     }
 }
 
diff --git a/MLKLexicalEnvironment.m b/MLKLexicalEnvironment.m
index 91ff351..af2a103 100644
--- a/MLKLexicalEnvironment.m
+++ b/MLKLexicalEnvironment.m
@@ -110,8 +110,8 @@ static MLKLexicalEnvironment *global_environment;
   if (![_variables environmentForSymbol:symbol]
       || [_variables environmentForSymbol:symbol] == global_environment->_variables)
     {
-      id *cell = [[MLKLexicalContext globalContext] bindingCellForSymbol:symbol];
-      return [*cell value];
+      id cell = [[MLKLexicalContext globalContext] bindingForSymbol:symbol];
+      return [cell value];
     }
   else
     {
@@ -124,8 +124,8 @@ static MLKLexicalEnvironment *global_environment;
   if (![_variables environmentForSymbol:symbol]
       || [_variables environmentForSymbol:symbol] == global_environment->_variables)
     {
-      id *cell = [[MLKLexicalContext globalContext] bindingCellForSymbol:symbol];
-      [*cell setValue:value];
+      id cell = [[MLKLexicalContext globalContext] bindingForSymbol:symbol];
+      [cell setValue:value];
     }
   else
     {
@@ -137,8 +137,8 @@ static MLKLexicalEnvironment *global_environment;
 {
   if (self == global_environment)
     {
-      id *cell = [[MLKLexicalContext globalContext] bindingCellForSymbol:symbol];
-      [*cell setValue:value];
+      id cell = [[MLKLexicalContext globalContext] bindingForSymbol:symbol];
+      [cell setValue:value];
     }
   else
     {
-- 
cgit v1.2.3