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).
-
#undefined_symbols ⇒ Object
Returns a set of symbols that have been used, but not defined.
-
#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.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 36 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 @symbol_tracker = SymbolTracker.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
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 159 160 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 103 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]
170 171 172 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 170 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.
218 219 220 221 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 218 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.
224 225 226 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 224 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.
229 230 231 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 229 def at_expr? value value.respond_to?(:[]) && value[0] == :'@' end |
#binop?(op) ⇒ Boolean
Tests if op is a binary operation.
234 235 236 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 234 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.
244 245 246 247 248 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 244 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.
252 253 254 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 252 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.
259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 259 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.
278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 278 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.
294 295 296 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 294 def emit code @sections[real_section_name(@section)] << code end |
#emit_label(name) ⇒ Object
Emits a label.
299 300 301 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 299 def emit_label name emit "#{name}:\n" end |
#emit_voodoo(*code) ⇒ Object
Emits a comment with the given Voodoo code.
304 305 306 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 304 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.
310 311 312 313 314 315 316 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 310 def export *symbols if real_section_name(section) == ".data" @relocated_symbols.merge symbols end @symbol_tracker.use *symbols 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.
178 179 180 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 178 def features @features end |
#function(formals, *code) ⇒ Object
Adds a function to the current section. Requires subclasses to implement begin_function and end_function.
320 321 322 323 324 325 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 320 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.
183 184 185 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 183 def gensym Environment.gensym end |
#global?(symbol) ⇒ Boolean
Tests if a symbol refers to a global.
328 329 330 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 328 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.
189 190 191 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 189 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.
334 335 336 337 338 339 340 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 334 def import *symbols if real_section_name(section) == ".data" @relocated_symbols.merge symbols end @symbol_tracker.define *symbols emit_import *symbols end |
#in_section(name, &block) ⇒ Object
Executes a block of code using the given section as the current section.
343 344 345 346 347 348 349 350 351 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 343 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.
354 355 356 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 354 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.
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 362 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 @symbol_tracker.define name 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.
381 382 383 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 381 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.
387 388 389 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 387 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.
393 394 395 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 393 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.
195 196 197 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 195 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.
200 201 202 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 200 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.
400 401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 400 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.
414 415 416 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 414 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.
419 420 421 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 419 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.
429 430 431 432 433 434 435 436 437 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 429 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.
442 443 444 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 442 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.
447 448 449 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 447 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.
456 457 458 459 460 461 462 463 464 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 456 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.
471 472 473 474 475 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 471 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.
485 486 487 488 489 490 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 485 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.
495 496 497 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 495 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.
504 505 506 507 508 509 510 511 512 513 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 504 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.
516 517 518 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 516 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.
531 532 533 534 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 531 def section name = nil self.section = name if name @section end |
#section=(name) ⇒ Object
Sets the current section.
521 522 523 524 525 526 527 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 521 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.
537 538 539 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 537 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.
543 544 545 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 543 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.
553 554 555 556 557 558 559 560 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 553 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.
548 549 550 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 548 def substitution? x x.respond_to?(:[]) && x[0] == :'%' end |
#symbol?(value) ⇒ Boolean
Tests if a value is a symbol.
563 564 565 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 563 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).
569 570 571 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 569 def symmetric_binop? op [:add, :and, :mul, :or, :xor].member? op end |
#undefined_symbols ⇒ Object
Returns a set of symbols that have been used, but not defined.
574 575 576 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 574 def undefined_symbols @symbol_tracker.used_but_undefined_symbols 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.
582 583 584 585 586 587 588 589 590 591 592 593 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 582 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.
597 598 599 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 597 def with_temporary &block with_temporaries 1, &block end |
#write(io) ⇒ Object
Writes generated code to the given IO object.
602 603 604 605 606 607 608 609 610 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 602 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 |