# encoding: utf-8 # frozen_string_literal: true module Carbon module Tacky class Instruction < Value # Generation logic for instructions. module Generation private # Generates a "normal" instruction. It maps the parameters, then sends # the instruction over to a builder for LLVM, before returning the # result of the instruction. # # @param context [Tacky::Context] The context. # @param block [::LLVM::BasicBlock] The block. # @return [::LLVM::Value] The result of the llvm instruction. def generate_normal(context, block) params = mapped_parameters(context) value = :_ block.build { |b| value = b.public_send(@instruction, *params) } value end def generate_null(context, _block) params = mapped_parameters(context) params.first.null end def generate_sizeof(context, _block) params = mapped_parameters(context) params.first.size end def generate_deref(context, _block) mapped_parameter(@parameters.first, context).element_type end def mapped_parameters(context) @parameters.map { |p| mapped_parameter(p, context) } end def typeof_value(value, context) case value when Concrete::Type value.sub(context.generics) when Tacky::Typed, Tacky::Parameter value.type.sub(context.generics) else fail ArgumentError, "Cannot typeof #{value.class}" end end def mapped_parameter(param, context) case param when Concrete::Type context.fetch(param.sub(context.generics)).last when Tacky::Reference then context.instructions.fetch(param.id) when Tacky::Parameter then context.params.fetch(param.value) when Tacky::Typed then mapped_parameter(param.value, context) when ::Integer, ::Float, ::String, ::LLVM::Value then param else fail ArgumentError, "Unexpected parameter #{param.class}" end end end end end end