Class: Voodoo::CommonCodeGenerator
- Inherits:
-
Object
- Object
- Voodoo::CommonCodeGenerator
- Defined in:
- lib/voodoo/generators/common_code_generator.rb
Overview
Common base class for code generators.
Code generators are expected to implement the following methods:
-
#new
-
#add
-
#add_function
-
#features
-
#gensym
-
#has_feature?
-
#output_file_name
-
#output_file_suffix
-
#saved_frame_size
This class contains base implementations of some of these methods, which can be used and/or overridden by subclasses.
An example of how to use the code generators provided by this module is provided on the main page of the documentation of the Voodoo module.
Direct Known Subclasses
Defined Under Namespace
Classes: Environment
Instance Method Summary collapse
-
#add(section, *code) ⇒ Object
Adds code to the given section.
-
#add_function(formals, *code) ⇒ Object
Adds a function.
-
#align(alignment = nil) ⇒ Object
Emits a directive to align the code or data following this statement.
-
#assymetric_binop?(op) ⇒ Boolean
Tests if op is a binary operation.
-
#at_expr?(value) ⇒ Boolean
Tests if a value is an at-expression.
-
#binop?(op) ⇒ Boolean
Tests if op is a binary operation.
-
#block(*code) ⇒ Object
Processes code in its own block.
-
#count_locals(statements) ⇒ Object
Returns the number of local variable slots required by a sequence of statements.
-
#default_alignment(section = @section) ⇒ Object
Returns the default alignment for the given section.
-
#each_statement(statements, &block) ⇒ Object
Invokes block with each statement in the given list of statements.
-
#emit(code) ⇒ Object
Adds code to the current section.
-
#emit_label(name) ⇒ Object
Emits a label.
-
#emit_voodoo(*code) ⇒ Object
Emits a comment with the given Voodoo code.
-
#export(*symbols) ⇒ Object
Declares that the given symbols are to be externally visible.
-
#features ⇒ Object
Returns a hash describing the features supported by this code generator.
-
#function(formals, *code) ⇒ Object
Adds a function to the current section.
-
#gensym ⇒ Object
Returns a new, unused symbol.
-
#global?(symbol) ⇒ Boolean
Tests if a symbol refers to a global.
-
#has_feature?(name) ⇒ Boolean
Returns true if a feature is supported by this generator, false otherwise.
-
#import(*symbols) ⇒ Object
Declares that the given symbols are imported from an external object.
-
#in_section(name, &block) ⇒ Object
Executes a block of code using the given section as the current section.
-
#initialize(params = {}) ⇒ CommonCodeGenerator
constructor
Initializes the code generator.
-
#integer?(value) ⇒ Boolean
Tests if a value is an integer.
-
#label(name) ⇒ Object
Creates a label.
-
#local_register(n) ⇒ Object
Returns the register in which the nth local (0-based) is stored, or nil if not stored in a register.
-
#number_of_register_arguments(n = @environment.args) ⇒ Object
Calculates the number of register arguments, given the total number of arguments.
-
#number_of_stack_arguments(n = @environment.args) ⇒ Object
Calculate the number of stack arguments, given the total number of arguments.
-
#output_file_name(input_name) ⇒ Object
Given an input file name, returns the canonical output file name for this code generator.
-
#output_file_suffix ⇒ Object
Returns the canonical output file suffix for this code generator.
-
#real_section_name(name) ⇒ Object
Gets the real name of a section.
-
#register?(x) ⇒ Boolean
Returns true if operand is a register, false otherwise.
-
#register_arg?(n) ⇒ Boolean
Returns true if the nth (0-based) argument is stored in a register.
-
#registers_for_locals(locals = []) ⇒ Object
Given some local variable names, returns the registers those variables are stored in.
-
#restore_frame(frame) ⇒ Object
Restores the frame saved at the given location.
-
#restore_locals(frame, *locals) ⇒ Object
Restores local variables from a saved frame.
-
#restore_registers_from_frame(frame, registers) ⇒ Object
Helper function for restore_frame and restore_locals.
-
#save_frame(frame) ⇒ Object
Saves the current frame to the given location.
-
#save_frame_and_locals(frame, *locals) ⇒ Object
Saves the current frame to the given location.
-
#save_locals(frame, *locals) ⇒ Object
Saves local variables to the given frame.
-
#save_registers_to_frame(frame, registers) ⇒ Object
Helper function for save_frame and save_locals.
-
#saved_frame_size ⇒ Object
Returns the number of bytes necessary to save the current frame.
-
#section(name = nil) ⇒ Object
Returns the name of the current section.
-
#section=(name) ⇒ Object
Sets the current section.
-
#section_alias(alias_name, original_name) ⇒ Object
Sets up alias_name to refer to the same section as original_name.
-
#stack_align(n) ⇒ Object
Given n, returns the nearest multiple of @STACK_ALIGNMENT that is >= n.
-
#substitute_number(key) ⇒ Object
Substitutes a numeric value for a given substitution key.
-
#substitution?(x) ⇒ Boolean
Tests if a value is a substitution.
-
#symbol?(value) ⇒ Boolean
Tests if a value is a symbol.
-
#symmetric_binop?(op) ⇒ Boolean
Test if op is a symmetric binary operation (i.e. it will yield the same result if the order of its source operands is changed).
-
#with_temporaries(n, &block) ⇒ Object
Executes a block of code, passing the block the name of
n
unused temporary registers. -
#with_temporary(&block) ⇒ Object
Executes a block of code, passing the block the name of an unused temporary register as its first argument.
-
#write(io) ⇒ Object
Writes generated code to the given IO object.
Constructor Details
#initialize(params = {}) ⇒ CommonCodeGenerator
Initializes the code generator. params is a hash of key-value pairs, and can be used to pass additional parameters to the generator. Standard parameters are :architecture and :format, which indicate the architecture and the output format. If these are not supplied, default values will be used. Subclasses may define additional parameters.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 35 def initialize params = {} @architecture = params[:architecture] || Config.default_architecture @format = params[:format] || Config.default_format @sections = {} @section_aliases = {} # Default section aliases. Subclasses can start from scratch by # doing @section_aliases = {} section_alias :code, ".text" section_alias :functions, :code section_alias :data, ".data" self.section = :code @top_level = Environment.initial_environment @environment = @top_level @output_file_suffix = '.o' @open_labels = [] # Labels for which we must emit size annotations @relocated_symbols = Set.new @features = { :voodoo => "1.1" # Voodoo language version } end |
Instance Method Details
#add(section, *code) ⇒ Object
Adds code to the given section.
Examples:
add :code, [:return, 0]
add :data, [:align], [:label, :xyzzy], [:word, 42]
This method implements the required functionality in terms of a number of methods for individual incantations. These must be implemented by subclasses, although default implementations may be provided by CommonCodeGenerator. The following list contains the methods that the add method relies on. Methods that are provided by this class have been marked with a star. In general, these methods will require some functionality to be implemented by subclasses.
-
#align (*)
-
#block (*)
-
#byte
-
#call
-
#comment
-
#emit_label_size
-
#end_if
-
#export (*)
-
#function (*)
-
#goto
-
#group
-
#ifeq
-
#ifge
-
#ifgt
-
#ifle
-
#iflt
-
#ifne
-
#import (*)
-
#label (*)
-
#let
-
#restore_frame (*)
-
#restore_locals (*)
-
#ret
-
#save_frame (*)
-
#save_locals (*)
-
#set
-
#set_byte
-
#set_word
-
#string
-
#word
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 101 def add section, *code in_section section do code.each do |action| keyword, args = action[0], action[1..-1] case keyword when :block emit_voodoo :block block *args emit_voodoo :end, :block when :function emit_voodoo :function, *args[0] function args[0], *args[1..-1] emit_voodoo :end, :function when :group emit_voodoo :group old_open_labels = @open_labels begin @open_labels = [] args.each { |statement| add section, statement } ensure @open_labels = old_open_labels end emit_voodoo :end, :group when :ifeq, :ifge, :ifgt, :ifle, :iflt, :ifne emit_voodoo keyword, *args[0] truebody = action[2] falsebody = action[3] send keyword, action[1][0], action[1][1] add section, *truebody if falsebody && !falsebody.empty? emit_voodoo :else ifelse add section, *falsebody end emit_voodoo :end, :if end_if when :label, :string, :word send *action when :return emit_voodoo *action send :ret, *args else emit_voodoo *action underscored = keyword.to_s.gsub('-', '_').to_sym send underscored, *args end # If we are on top-level and we have open labels and we just # emitted something that isn't a label, emit size annotations # for all open labels. if !@open_labels.empty? && keyword != :label && @environment == @top_level @open_labels.each { |name| emit_label_size name } @open_labels.clear end end end end |
#add_function(formals, *code) ⇒ Object
Adds a function.
Parameters:
- formals
-
an Array of formal parameter names
- code
-
an Array of actions to be used as the function’s body
Example:
add_function [:n], [:return, :add, :n, 1]
168 169 170 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 168 def add_function formals, *code add :functions, [:function, formals] + code end |
#align(alignment = nil) ⇒ Object
Emits a directive to align the code or data following this statement. If alignment is given, aligns on the next multiple of alignment bytes. Else, uses the default alignment for the current section.
This method requires the presence of a default_alignment method to calculate the default alignment for a given section, and an emit_align method to actually emit the target-specific code to align to a multiple of a given number of bytes. An implementation of default_alignment is provided in this class.
216 217 218 219 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 216 def align alignment = nil alignment = default_alignment if alignment == nil emit_align alignment unless alignment == 0 end |
#assymetric_binop?(op) ⇒ Boolean
Tests if op is a binary operation.
222 223 224 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 222 def assymetric_binop? op [:asr, :bsr, :div, :mod, :rol, :ror, :shl, :shr, :sub].member?(op) end |
#at_expr?(value) ⇒ Boolean
Tests if a value is an at-expression.
227 228 229 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 227 def at_expr? value value.respond_to?(:[]) && value[0] == :'@' end |
#binop?(op) ⇒ Boolean
Tests if op is a binary operation.
232 233 234 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 232 def binop? op assymetric_binop?(op) || symmetric_binop?(op) end |
#block(*code) ⇒ Object
Processes code in its own block. Local variables can be introduced inside the block. They will be deleted at the end of the block.
This method requires subclasses to implement begin_block and end_block.
242 243 244 245 246 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 242 def block *code begin_block *code code.each { |action| add section, action } end_block end |
#count_locals(statements) ⇒ Object
Returns the number of local variable slots required by a sequence of statements.
250 251 252 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 250 def count_locals statements count_locals_helper statements, 0, 0 end |
#default_alignment(section = @section) ⇒ Object
Returns the default alignment for the given section. If no section is specified, returns the alignment for the current section.
257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 257 def default_alignment section = @section # Get default alignment case section when :code @CODE_ALIGNMENT when :data @DATA_ALIGNMENT when :function @FUNCTION_ALIGNMENT else # Use data alignment as default @DATA_ALIGNMENT end end |
#each_statement(statements, &block) ⇒ Object
Invokes block with each statement in the given list of statements. This iterator also descends into nested statements, calling block first with the outer statement, and then for each inner statement.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 276 def each_statement statements, &block statements.each do |statement| yield statement case statement[0] when :block each_statement statement[1..-1], &block when :function each_statement statement[2..-1], &block when :ifeq, :ifle, :iflt, :ifge, :ifgt, :ifne each_statement statement[2], &block each_statement(statement[3], &block) if statement.length > 3 end end end |
#emit(code) ⇒ Object
Adds code to the current section.
292 293 294 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 292 def emit code @sections[real_section_name(@section)] << code end |
#emit_label(name) ⇒ Object
Emits a label.
297 298 299 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 297 def emit_label name emit "#{name}:\n" end |
#emit_voodoo(*code) ⇒ Object
Emits a comment with the given Voodoo code.
302 303 304 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 302 def emit_voodoo *code comment code.join(' ') end |
#export(*symbols) ⇒ Object
Declares that the given symbols are to be externally visible. Requires subclasses to implement emit_export.
308 309 310 311 312 313 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 308 def export *symbols if real_section_name(section) == ".data" @relocated_symbols.merge symbols end emit_export *symbols end |
#features ⇒ Object
Returns a hash describing the features supported by this code generator. The keys in this hash are the names of the supported features. The associated values are strings providing additional information about the feature, such as a version number.
176 177 178 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 176 def features @features end |
#function(formals, *code) ⇒ Object
Adds a function to the current section. Requires subclasses to implement begin_function and end_function.
317 318 319 320 321 322 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 317 def function formals, *code nlocals = count_locals code begin_function formals, nlocals code.each { |action| add section, action } end_function end |
#gensym ⇒ Object
Returns a new, unused symbol.
181 182 183 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 181 def gensym Environment.gensym end |
#global?(symbol) ⇒ Boolean
Tests if a symbol refers to a global.
325 326 327 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 325 def global? symbol symbol?(symbol) && @environment[symbol] == nil end |
#has_feature?(name) ⇒ Boolean
Returns true if a feature is supported by this generator, false otherwise.
187 188 189 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 187 def has_feature? name @features.has_key? name end |
#import(*symbols) ⇒ Object
Declares that the given symbols are imported from an external object. Requires subclasses to implement emit_import.
331 332 333 334 335 336 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 331 def import *symbols if real_section_name(section) == ".data" @relocated_symbols.merge symbols end emit_import *symbols end |
#in_section(name, &block) ⇒ Object
Executes a block of code using the given section as the current section.
339 340 341 342 343 344 345 346 347 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 339 def in_section name, &block oldsection = @section self.section = name begin yield ensure self.section = oldsection end end |
#integer?(value) ⇒ Boolean
Tests if a value is an integer.
350 351 352 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 350 def integer? value value.kind_of? Integer end |
#label(name) ⇒ Object
Creates a label. Besides emitting the label name, this also annotates top-level objects with type and size as required for ELF shared libraries. Requires subclasses to emit emit_label and emit_label_type.
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 358 def label name # If we are at top level, emit type directive and arrange to # emit size directive. if @environment == @top_level case real_section_name(section) when ".text" type = :code else type = :data end emit_label_type name, type @open_labels << name end emit_label name end |
#local_register(n) ⇒ Object
Returns the register in which the nth local (0-based) is stored, or nil if not stored in a register.
376 377 378 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 376 def local_register n @LOCAL_REGISTERS[n + number_of_register_arguments] end |
#number_of_register_arguments(n = @environment.args) ⇒ Object
Calculates the number of register arguments, given the total number of arguments.
382 383 384 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 382 def number_of_register_arguments n = @environment.args [n, @NREGISTER_ARGS].min end |
#number_of_stack_arguments(n = @environment.args) ⇒ Object
Calculate the number of stack arguments, given the total number of arguments.
388 389 390 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 388 def number_of_stack_arguments n = @environment.args [0, n - @NREGISTER_ARGS].max end |
#output_file_name(input_name) ⇒ Object
Given an input file name, returns the canonical output file name for this code generator.
193 194 195 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 193 def output_file_name input_name input_name.sub(/\.voo$/, '') + @output_file_suffix end |
#output_file_suffix ⇒ Object
Returns the canonical output file suffix for this code generator.
198 199 200 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 198 def output_file_suffix @output_file_suffix end |
#real_section_name(name) ⇒ Object
Gets the real name of a section. Given a section name which may be an alias, this method returns the real name of the section.
395 396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 395 def real_section_name name given_name = name while true x = @section_aliases[name] break if x == nil # Not an alias, exit loop and return name name = x # If name == given_name, we're back where we started. Continuing # would have us loop forever. Just return what we have now. break if name == given_name end name end |
#register?(x) ⇒ Boolean
Returns true if operand is a register, false otherwise.
409 410 411 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 409 def register? x x.kind_of? Symbol end |
#register_arg?(n) ⇒ Boolean
Returns true if the nth (0-based) argument is stored in a register.
414 415 416 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 414 def register_arg? n n < @NREGISTER_ARGS end |
#registers_for_locals(locals = []) ⇒ Object
Given some local variable names, returns the registers those variables are stored in. If no variable names are given, returns all registers used to store local variables.
Requires @LOCAL_REGISTERS_SET, a set of registers that are used to store local variables.
424 425 426 427 428 429 430 431 432 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 424 def registers_for_locals locals = [] locals = @environment.symbols.keys if locals.empty? registers = [] locals.each do |sym| reg = @environment[sym] registers << reg if @LOCAL_REGISTERS_SET.include? @environment[sym] end registers end |
#restore_frame(frame) ⇒ Object
Restores the frame saved at the given location. Requires @SAVE_FRAME_REGISTERS, an array of register names that must be restored.
437 438 439 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 437 def restore_frame frame restore_registers_from_frame frame, @SAVE_FRAME_REGISTERS end |
#restore_locals(frame, *locals) ⇒ Object
Restores local variables from a saved frame.
442 443 444 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 442 def restore_locals frame, *locals restore_registers_from_frame frame, registers_for_locals(locals) end |
#restore_registers_from_frame(frame, registers) ⇒ Object
Helper function for restore_frame and restore_locals.
Requires @SAVED_FRAME_LAYOUT, a map from register names to positions in a saved frame, emit_load_word to load registers from memory, and load_value_into_register to load a Voodoo value into a CPU register.
451 452 453 454 455 456 457 458 459 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 451 def restore_registers_from_frame frame, registers with_temporary do |temporary| load_value_into_register frame, temporary registers.each do |register| i = @SAVED_FRAME_LAYOUT[register] emit_load_word register, temporary, i end end end |
#save_frame(frame) ⇒ Object
Saves the current frame to the given location.
Requires @SAVE_FRAME_REGISTERS, an array of names of registers that must be saved, and @LOCAL_REGISTERS, the list of registers that are used to store values of local variables.
466 467 468 469 470 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 466 def save_frame frame registers_to_save = @SAVE_FRAME_REGISTERS - (@saved_registers & @LOCAL_REGISTERS) save_registers_to_frame frame, registers_to_save end |
#save_frame_and_locals(frame, *locals) ⇒ Object
Saves the current frame to the given location. If locals are given, saves those locals to the frame, too. If no locals are given, saves all locals.
Requires @SAVE_FRAME_REGISTERS, an array of names of registers that must be saved, and @LOCAL_REGISTERS, the list of registers that are used to store values of local variables.
480 481 482 483 484 485 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 480 def save_frame_and_locals frame, *locals registers_to_save = (@SAVE_FRAME_REGISTERS - (@saved_registers & @LOCAL_REGISTERS)) | registers_for_locals(locals) save_registers_to_frame frame, registers_to_save end |
#save_locals(frame, *locals) ⇒ Object
Saves local variables to the given frame. If no locals are specified, saves all locals. If locals are specified, saves only the specified ones.
490 491 492 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 490 def save_locals frame, *locals save_registers_to_frame frame, registers_for_locals(locals) end |
#save_registers_to_frame(frame, registers) ⇒ Object
Helper function for save_frame and save_locals.
Requires @SAVED_FRAME_LAYOUT, a map from register names to positions in a saved frame, emit_store_word to store registers in memory, and load_value_into_register to load a Voodoo value into a CPU register.
499 500 501 502 503 504 505 506 507 508 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 499 def save_registers_to_frame frame, registers return if registers.empty? with_temporary do |temporary| load_value_into_register frame, temporary registers.each do |register| i = @SAVED_FRAME_LAYOUT[register] emit_store_word register, temporary, i end end end |
#saved_frame_size ⇒ Object
Returns the number of bytes necessary to save the current frame.
511 512 513 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 511 def saved_frame_size @SAVED_FRAME_LAYOUT.length * @WORDSIZE end |
#section(name = nil) ⇒ Object
Returns the name of the current section. If a name is given, sets the name of the current section first.
526 527 528 529 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 526 def section name = nil self.section = name if name @section end |
#section=(name) ⇒ Object
Sets the current section.
516 517 518 519 520 521 522 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 516 def section= name real_name = real_section_name name @section = name unless @sections.has_key? real_name @sections[real_name] = '' end end |
#section_alias(alias_name, original_name) ⇒ Object
Sets up alias_name to refer to the same section as original_name.
532 533 534 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 532 def section_alias alias_name, original_name @section_aliases[alias_name] = original_name end |
#stack_align(n) ⇒ Object
Given n, returns the nearest multiple of @STACK_ALIGNMENT that is >= n.
538 539 540 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 538 def stack_align n (n + @STACK_ALIGNMENT - 1) / @STACK_ALIGNMENT * @STACK_ALIGNMENT end |
#substitute_number(key) ⇒ Object
Substitutes a numeric value for a given substitution key.
548 549 550 551 552 553 554 555 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 548 def substitute_number key case key when :'saved-frame-size' saved_frame_size else @features[key].to_i end end |
#substitution?(x) ⇒ Boolean
Tests if a value is a substitution.
543 544 545 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 543 def substitution? x x.respond_to?(:[]) && x[0] == :'%' end |
#symbol?(value) ⇒ Boolean
Tests if a value is a symbol.
558 559 560 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 558 def symbol? value value.kind_of? Symbol end |
#symmetric_binop?(op) ⇒ Boolean
Test if op is a symmetric binary operation (i.e. it will yield the same result if the order of its source operands is changed).
564 565 566 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 564 def symmetric_binop? op [:add, :and, :mul, :or, :xor].member? op end |
#with_temporaries(n, &block) ⇒ Object
Executes a block of code, passing the block the name of n
unused temporary registers.
Requires @TEMPORARIES, an array of temporary registers.
572 573 574 575 576 577 578 579 580 581 582 583 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 572 def with_temporaries n, &block if @TEMPORARIES.length < n raise "Out of temporary registers" else temporaries = @TEMPORARIES.shift n begin yield *temporaries ensure @TEMPORARIES.unshift *temporaries end end end |
#with_temporary(&block) ⇒ Object
Executes a block of code, passing the block the name of an unused temporary register as its first argument.
587 588 589 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 587 def with_temporary &block with_temporaries 1, &block end |
#write(io) ⇒ Object
Writes generated code to the given IO object.
592 593 594 595 596 597 598 599 600 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 592 def write io @sections.each do |section,code| unless code.empty? io.puts ".section #{section.to_s}" io.puts code io.puts end end end |