Beispiel #1
0
 public function gen()
 {
     $ir = "";
     $leftname = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->left);
     $left = new $leftname($this->obj->left);
     $ir .= $left->gen();
     $rightname = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->right);
     $right = new $rightname($this->obj->right);
     $ir .= $right->gen();
     $leftreg = \Tables::$register_alloc - 1;
     $rightreg = $leftreg + 1;
     if ($this->obj->left instanceof \Parser\Parsers\Integer) {
         $reg1 = \Tables::alloc();
         /* holds the left value */
         $ir .= "\t%{$reg1} = load i32* %{$leftreg}" . PHP_EOL;
     } else {
         $reg1 = $leftreg;
     }
     if ($this->obj->right instanceof \Parser\Parsers\Integer) {
         $reg2 = \Tables::alloc();
         /* holds the right value */
         $ir .= "\t%{$reg2} = load i32* %{$rightreg}" . PHP_EOL;
     } else {
         $reg2 = $rightreg;
     }
     $reg3 = \Tables::alloc();
     /* holds the result */
     $ir .= "\t%{$reg3} = sub nsw i32 %{$reg1}, %{$reg2}" . PHP_EOL;
     $this->resultreg = $reg3;
     return $ir;
 }
Beispiel #2
0
 public function gen()
 {
     $ir = "";
     foreach ($this->ast as $item) {
         $name = "\\Codegen\\Generator\\" . \Misc::baseClass($item);
         $gen = new $name($item);
         $ir .= $gen->gen();
     }
     return $ir;
 }
Beispiel #3
0
 public function gen()
 {
     if (is_object($this->obj->content[0])) {
         /* it is a arithmetic expression */
         $ir = "";
         $name = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->content[0]);
         $obj = new $name($this->obj->content[0]);
         $var =& \Tables::updateLocalVariable($this->obj->function, $this->obj->name);
         $ir .= $obj->gen();
         for ($i = 0; $i <= $this->obj->line; $i++) {
             if (isset($var->type[$i])) {
                 $type = $var->type[$i];
             }
         }
         $var->type[$this->obj->line] = $type | \Tables::POINTER;
         $var->type[$this->obj->line] &= ~\Tables::POINTER;
         $var->name = \Tables::$register_alloc;
     } elseif (!is_null(\Tables::localVariable($this->obj->function, $this->obj->name))) {
         /* allocate and get everything ready */
         $reg1 = \Tables::alloc();
         /* the reg number */
         $reg2 = \Tables::alloc();
         /* the reg number */
         $var =& \Tables::updateLocalVariable($this->obj->function, $this->obj->name);
         /* our reference to the variable */
         /* get the correct type */
         for ($i = 0; $i <= $this->obj->line; $i++) {
             if (isset($var->type[$i])) {
                 $type = $var->type[$i];
             }
         }
         $type = \Misc::getType($type);
         /* its type */
         $name = "\\Codegen\\Generator\\" . \Misc::baseClass($this->obj->content[0]);
         $obj = new $name($this->obj->content[0]);
         /* the code that is to be moved into the reg */
         $code = $obj->arg();
         /* change the name of the variable to the new register */
         $var->name = $reg2;
         /* generate the code */
         $ir = "\t%{$reg1} = alloca {$type}" . PHP_EOL;
         /* allocate the register */
         $ir .= "\tstore " . $code . ", {$type}* %{$reg1}" . PHP_EOL;
         /* store our value in it */
         $ir .= "\t%{$reg2} = load {$type}* %{$reg1}" . PHP_EOL;
         /* move it into a register we don't have to reference it as a pointer */
     }
     return $ir;
 }
Beispiel #4
0
 public function gen()
 {
     $ir = "";
     if (\Tables::declaration($this->obj->name) || \Tables::func($this->obj->name)) {
         $gen = array();
         $ir .= "\t; prepare the arguments" . PHP_EOL;
         for ($i = 0; $i < count($this->obj->content); $i++) {
             $arg = $this->obj->content[$i];
             if (\Misc::baseClass($arg) == "Addition" || \Misc::baseClass($arg) == "Subtraction" || \Misc::baseClass($arg) == "Multiplication" || \Misc::baseClass($arg) == "Division" || \Misc::baseClass($arg) == "Call") {
                 $name = "\\Codegen\\Generator\\" . \Misc::baseClass($arg);
                 $obj = new $name($arg);
                 $ir .= $obj->gen();
                 $gen[$i] = $obj;
             }
         }
         if (\Tables::declaration($this->obj->name)) {
             $dec = \Tables::getDeclaration($this->obj->name);
         } elseif (\Tables::func($this->obj->name)) {
             $dec = \Tables::getFunc($this->obj->name);
         }
         $reg = \Tables::alloc();
         $this->result = $reg;
         $ir .= "\t; call {$dec->name}" . PHP_EOL;
         if (empty($dec->args)) {
             $ir .= "\t%{$reg} = call {$dec->return} @{$dec->name}";
         } else {
             $ir .= "\t%{$reg} = call {$dec->return} {$dec->args}* @{$dec->name}";
         }
         if (count($this->obj->content) > 0) {
             for ($i = 0; $i < count($this->obj->content); $i++) {
                 $arg = $this->obj->content[$i];
                 if (isset($gen[$i]) && !empty($gen[$i])) {
                     $obj = $gen[$i];
                 } else {
                     $name = "\\Codegen\\Generator\\" . \Misc::baseClass($arg);
                     $obj = new $name($arg);
                 }
                 $ir .= $obj->arg() . ", ";
             }
             $ir = substr($ir, 0, -2);
         }
         $ir .= ")" . PHP_EOL;
         $ir .= "\t; end of call to {$dec->name}" . PHP_EOL . PHP_EOL;
     } else {
         error("unknown function in line {$this->obj->line}");
     }
     return $ir;
 }
Beispiel #5
0
 public function gen()
 {
     $ir = "";
     $item = $this->obj->content[0];
     if ($item instanceof \Parser\Parsers\Integer) {
         $ir .= "\tret i32 {$item->value}" . PHP_EOL;
     } elseif ($item instanceof \Parser\Parsers\Variable) {
         $val = new \Codegen\Generator\Variable($item);
         $ir .= "\tret " . $val->arg() . PHP_EOL;
         /* TODO: maybe have a function that checks for arithmetic parsers/codegenerators? */
     } elseif ($item instanceof \Parser\Parsers\Addition || $item instanceof \Parser\Parsers\Subtraction || $item instanceof \Parser\Parsers\Multiplication || $item instanceof \Parser\Parsers\Division) {
         $name = "\\Codegen\\Generator\\" . \Misc::baseClass($item);
         $val = new $name($item);
         $ir .= $val->gen();
         $ir .= "\tret i32 %" . \Tables::$register_alloc . PHP_EOL;
     } else {
         error("invalid return type '" . \Misc::baseClass($item) . "' in line {$this->obj->line}");
     }
     return $ir;
 }
Beispiel #6
0
 public function analyze($ast, $parent = NULL)
 {
     /* holds the name of the currently compiled function */
     $function = "";
     foreach ($ast as $i => $node) {
         /* set the function name in the objects */
         if ($node instanceof \Parser\Parsers\FunctionDefinition) {
             $function = $node->name;
             $node->function = $node->name;
         } elseif (!empty($node->function)) {
             $function = $node->function;
         } else {
             if (isset($node->name) && $node->name == "extern") {
                 continue;
             } elseif (!empty($function)) {
                 $node->function = $function;
             } else {
                 if (!empty($parent->function)) {
                     $node->function = $parent->function;
                 } elseif (!empty($function)) {
                     $node->function = $function;
                 }
             }
         }
         /* set the arguments as local variables */
         if ($node instanceof \Parser\Parsers\FunctionDefinition && count($node->arguments) > 0) {
             foreach ($node->arguments as $arg) {
                 \Tables::addLocalVariable($function, $arg->name);
             }
         }
         if ($node instanceof \Parser\Parsers\Assignment) {
             /* deal with assignments */
             if (is_object($node->content)) {
                 if (\Tables::localVariable($node->function, $node->name)) {
                     $var =& \Tables::updateLocalVariable($node->function, $node->name);
                 } else {
                     $var =& \Tables::addLocalVariable($node->function, $node->name);
                 }
                 $var->type[$node->line] = \Tables::I32;
                 continue;
             }
             switch (\Misc::baseClass($node->content[0])) {
                 case "String":
                     $type = \Tables::STRING;
                     break;
                 case "Integer":
                     $type = \Tables::I32;
                     break;
                 case "Addition":
                 case "Subtraction":
                 case "Multiplication":
                 case "Division":
                     $type = \Tables::I32;
                     break;
                 default:
                     error("unknown assignment type '" . \Misc::baseClass($node->content[0]) . "' in line {$node->line}");
             }
             if (\Tables::localVariable($node->function, $node->name)) {
                 $var =& \Tables::updateLocalVariable($node->function, $node->name);
             } else {
                 $var =& \Tables::addLocalVariable($node->function, $node->name);
             }
             $var->type[$node->line] = $type;
         } elseif (!$node instanceof \Parser\Parsers\Variable && count($node->content) > 0) {
             /* analyze recursively if needed */
             if ($node instanceof \Parser\Parsers\FunctionDefinition && !empty($node->arguments)) {
                 foreach ($node->arguments as $arg) {
                     $arg->function = $function;
                 }
             }
             $this->analyze($node->content, $node);
         } elseif ($node instanceof \Parser\Parsers\Variable) {
             /* do type inference based on printf */
             if ($parent instanceof \Parser\Parsers\Call) {
                 if ($parent->name == "printf") {
                     $matches = array();
                     preg_match_all("/%[scdiu]/", $ast[0]->string, $matches);
                     $format = substr($matches[0][$i - 1], -1);
                     $type = 0;
                     switch ($format) {
                         case 'd':
                         case 'i':
                         case 'c':
                             $type |= \Tables::I32;
                             break;
                         case 's':
                             $type |= \Tables::STRING;
                     }
                     $var =& \Tables::updateLocalVariable($node->function, $node->name);
                     if ($var == NULL) {
                         continue;
                     }
                     $node->type[$node->line] = $type;
                 }
             }
         }
     }
 }