// File: rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::to_expression[abi:cxx11](unsigned int)
string CompilerGLSL::to_expression(uint32_t id)
{
	auto itr = invalid_expressions.find(id);
	if (itr != end(invalid_expressions))
		handle_invalid_expression(id);

	if (ir.ids[id].get_type() == TypeExpression)
	{
		// We might have a more complex chain of dependencies.
		// A possible scenario is that we
		//
		// %1 = OpLoad
		// %2 = OpDoSomething %1 %1. here %2 will have a dependency on %1.
		// %3 = OpDoSomethingAgain %2 %2. Here %3 will lose the link to %1 since we don't propagate the dependencies like that.
		// OpStore %1 %foo // Here we can invalidate %1, and hence all expressions which depend on %1. Only %2 will know since it's part of invalid_expressions.
		// %4 = OpDoSomethingAnotherTime %3 %3 // If we forward all expressions we will see %1 expression after store, not before.
		//
		// However, we can propagate up a list of depended expressions when we used %2, so we can check if %2 is invalid when reading %3 after the store,
		// and see that we should not forward reads of the original variable.
		auto &expr = get<SPIRExpression>(id);
		for (uint32_t dep : expr.expression_dependencies)
			if (invalid_expressions.find(dep) != end(invalid_expressions))
				handle_invalid_expression(dep);
	}

	track_expression_read(id);

	switch (ir.ids[id].get_type())
	{
	case TypeExpression:
	{
		auto &e = get<SPIRExpression>(id);
		if (e.base_expression)
			return to_enclosed_expression(e.base_expression) + e.expression;
		else if (e.need_transpose)
		{
			bool is_packed = has_decoration(id, DecorationCPacked);
			return convert_row_major_matrix(e.expression, get<SPIRType>(e.expression_type), is_packed);
		}
		else
		{
			if (force_recompile)
			{
				// During first compilation phase, certain expression patterns can trigger exponential growth of memory.
				// Avoid this by returning dummy expressions during this phase.
				// Do not use empty expressions here, because those are sentinels for other cases.
				return "_";
			}
			else
				return e.expression;
		}
	}

	case TypeConstant:
	{
		auto &c = get<SPIRConstant>(id);
		auto &type = get<SPIRType>(c.constant_type);

		// WorkGroupSize may be a constant.
		auto &dec = ir.meta[c.self].decoration;
		if (dec.builtin)
			return builtin_to_glsl(dec.builtin_type, StorageClassGeneric);
		else if (c.specialization && options.vulkan_semantics)
			return to_name(id);
		else if (c.is_used_as_lut)
			return to_name(id);
		else if (type.basetype == SPIRType::Struct && !backend.can_declare_struct_inline)
			return to_name(id);
		else if (!type.array.empty() && !backend.can_declare_arrays_inline)
			return to_name(id);
		else
			return constant_expression(c);
	}

	case TypeConstantOp:
		if (options.vulkan_semantics)
			return to_name(id);
		else
			return constant_op_expression(get<SPIRConstantOp>(id));

	case TypeVariable:
	{
		auto &var = get<SPIRVariable>(id);
		// If we try to use a loop variable before the loop header, we have to redirect it to the static expression,
		// the variable has not been declared yet.
		if (var.statically_assigned || (var.loop_variable && !var.loop_variable_enable))
			return to_expression(var.static_expression);
		else if (var.deferred_declaration)
		{
			var.deferred_declaration = false;
			return variable_decl(var);
		}
		else if (flattened_structs.count(id))
		{
			return load_flattened_struct(var);
		}
		else
		{
			auto &dec = ir.meta[var.self].decoration;
			if (dec.builtin)
				return builtin_to_glsl(dec.builtin_type, var.storage);
			else
				return to_name(id);
		}
	}

	case TypeCombinedImageSampler:
		// This type should never be taken the expression of directly.
		// The intention is that texture sampling functions will extract the image and samplers
		// separately and take their expressions as needed.
		// GLSL does not use this type because OpSampledImage immediately creates a combined image sampler
		// expression ala sampler2D(texture, sampler).
		SPIRV_CROSS_THROW("Combined image samplers have no default expression representation.");

	case TypeAccessChain:
		// We cannot express this type. They only have meaning in other OpAccessChains, OpStore or OpLoad.
		SPIRV_CROSS_THROW("Access chains have no default expression representation.");

	default:
		return to_name(id);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x190, %rsp            # imm = 0x190
movq %rdi, -0x150(%rbp)
movq %rdi, %rax
movq %rax, -0x148(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x140(%rbp)
addq $0x198, %rdi            # imm = 0x198
leaq -0x14(%rbp), %rsi
callq 0x2ff00
movq -0x140(%rbp), %rdi
movq %rax, -0x20(%rbp)
addq $0x198, %rdi            # imm = 0x198
callq 0x2ff30
movq %rax, -0x28(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x2fed0
testb $0x1, %al
jne 0x71bc0
jmp 0x71bcf
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x72440
movq -0x140(%rbp), %rdi
addq $0x8, %rdi
addq $0x18, %rdi
movl -0x14(%rbp), %eax
movl %eax, %esi
callq 0xbdb0
movq %rax, %rdi
callq 0xfa00
cmpl $0x9, %eax
jne 0x71cb9
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x2e850
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
addq $0x40, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x86d0
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
callq 0x8700
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x8730
testb $0x1, %al
jne 0x71c45
jmp 0x71cb7
leaq -0x40(%rbp), %rdi
callq 0x8770
movq -0x140(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x4c(%rbp)
addq $0x198, %rdi            # imm = 0x198
leaq -0x4c(%rbp), %rsi
callq 0x2ff00
movq -0x140(%rbp), %rdi
movq %rax, -0x58(%rbp)
addq $0x198, %rdi            # imm = 0x198
callq 0x2ff30
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x2fed0
testb $0x1, %al
jne 0x71c98
jmp 0x71ca7
movq -0x140(%rbp), %rdi
movl -0x4c(%rbp), %esi
callq 0x72440
jmp 0x71ca9
leaq -0x40(%rbp), %rdi
callq 0x8790
jmp 0x71c32
jmp 0x71cb9
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x729b0
movq -0x140(%rbp), %rdi
addq $0x20, %rdi
movl -0x14(%rbp), %eax
movl %eax, %esi
callq 0xbdb0
movq %rax, %rdi
callq 0xfa00
addl $-0x2, %eax
movl %eax, %ecx
movq %rcx, -0x158(%rbp)
subl $0xa, %eax
ja 0x72407
movq -0x158(%rbp), %rax
leaq 0xce4d0(%rip), %rcx     # 0x1401d8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x2e850
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
cmpl $0x0, 0xc(%rax)
je 0x71da0
movq -0x140(%rbp), %rsi
movq -0x68(%rbp), %rax
movl 0xc(%rax), %edx
leaq -0x88(%rbp), %rdi
movq %rdi, -0x160(%rbp)
callq 0x72630
movq -0x150(%rbp), %rdi
movq -0x160(%rbp), %rsi
movq -0x68(%rbp), %rdx
addq $0x10, %rdx
callq 0xa1530
jmp 0x71d6c
leaq -0x88(%rbp), %rdi
callq 0x7708
jmp 0x72423
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x7708
jmp 0x72433
movq -0x68(%rbp), %rax
testb $0x1, 0x39(%rax)
je 0x71e62
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
movl $0xa, %edx
callq 0x1f560
movb %al, -0x95(%rbp)
movq -0x68(%rbp), %rsi
addq $0x10, %rsi
leaq -0xb8(%rbp), %rdi
callq 0x7170
movq -0x140(%rbp), %rdi
movq -0x68(%rbp), %rax
movl 0x30(%rax), %esi
callq 0xea90
movq %rax, -0x168(%rbp)
jmp 0x71df8
movq -0x168(%rbp), %rcx
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq (%rsi), %rax
movq 0x118(%rax), %rax
movzbl -0x95(%rbp), %r8d
andl $0x1, %r8d
leaq -0xb8(%rbp), %rdx
callq *%rax
jmp 0x71e2e
leaq -0xb8(%rbp), %rdi
callq 0x7708
jmp 0x72423
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x7708
jmp 0x72433
movq -0x140(%rbp), %rax
testb $0x1, 0x1d0(%rax)
je 0x71ed5
leaq -0xb9(%rbp), %rdi
movq %rdi, -0x170(%rbp)
callq 0x7650
movq -0x150(%rbp), %rdi
movq -0x170(%rbp), %rdx
leaq 0xd6684(%rip), %rsi     # 0x14851e
callq 0x7520
jmp 0x71ea1
leaq -0xb9(%rbp), %rdi
callq 0x73d0
jmp 0x72423
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0xb9(%rbp), %rdi
callq 0x73d0
jmp 0x72433
movq -0x150(%rbp), %rdi
movq -0x68(%rbp), %rsi
addq $0x10, %rsi
callq 0x7170
jmp 0x72423
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x31910
movq -0x140(%rbp), %rdi
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movl 0xc(%rax), %esi
callq 0xea90
movq -0x140(%rbp), %rdi
movq %rax, -0xd0(%rbp)
addq $0x8, %rdi
addq $0x30, %rdi
movq -0xc8(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, %esi
callq 0xead0
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
testb $0x1, 0xcc(%rax)
je 0x71f86
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq -0xd8(%rbp), %rax
movl 0xa0(%rax), %edx
movq (%rsi), %rax
movl $0x8, %ecx
callq *0xa0(%rax)
jmp 0x72423
movq -0xc8(%rbp), %rax
testb $0x1, 0x108(%rax)
je 0x71fc7
movq -0x140(%rbp), %rax
testb $0x1, 0x43e(%rax)
je 0x71fc7
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
jmp 0x72423
movq -0xc8(%rbp), %rax
testb $0x1, 0x10a(%rax)
je 0x71ff8
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
jmp 0x72423
movq -0xd0(%rbp), %rax
cmpl $0xc, 0xc(%rax)
jne 0x72036
movq -0x140(%rbp), %rax
testb $0x1, 0x626(%rax)
jne 0x72036
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
jmp 0x72423
movq -0xd0(%rbp), %rdi
addq $0x20, %rdi
callq 0x8690
testb $0x1, %al
jne 0x7207b
movq -0x140(%rbp), %rax
testb $0x1, 0x627(%rax)
jne 0x7207b
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
jmp 0x72423
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq -0xc8(%rbp), %rdx
callq 0x64bc0
jmp 0x72423
movq -0x140(%rbp), %rax
testb $0x1, 0x43e(%rax)
je 0x720cb
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
jmp 0x72423
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0xa1580
movq -0x150(%rbp), %rdi
movq -0x140(%rbp), %rsi
movq %rax, %rdx
callq 0x63510
jmp 0x72423
movq -0x140(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0xfec0
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
testb $0x1, 0x39(%rax)
jne 0x72132
movq -0xe0(%rbp), %rax
testb $0x1, 0x64(%rax)
je 0x72154
movq -0xe0(%rbp), %rax
testb $0x1, 0x65(%rax)
jne 0x72154
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq -0xe0(%rbp), %rax
movl 0x3c(%rax), %edx
callq 0x71b50
jmp 0x72423
movq -0xe0(%rbp), %rax
testb $0x1, 0x59(%rax)
je 0x7218b
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq -0xe0(%rbp), %rax
movb $0x0, 0x59(%rax)
movq -0xe0(%rbp), %rdx
callq 0x62d60
jmp 0x72423
movq -0x140(%rbp), %rdi
addq $0x6b0, %rdi            # imm = 0x6B0
leaq -0x14(%rbp), %rsi
callq 0x13520
cmpq $0x0, %rax
je 0x721c7
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq -0xe0(%rbp), %rdx
callq 0x72a40
jmp 0x72423
movq -0x140(%rbp), %rdi
addq $0x8, %rdi
addq $0x30, %rdi
movq -0xe0(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, %esi
callq 0xead0
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rax
testb $0x1, 0xcc(%rax)
je 0x72231
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movq -0xe8(%rbp), %rax
movl 0xa0(%rax), %edx
movq -0xe0(%rbp), %rax
movl 0x10(%rax), %ecx
movq (%rsi), %rax
callq *0xa0(%rax)
jmp 0x72423
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
jmp 0x72423
movb $0x1, -0x10a(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x180(%rbp)
leaq -0x109(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0x7650
movq -0x178(%rbp), %rdx
leaq 0xd0287(%rip), %rsi     # 0x142512
leaq -0x108(%rbp), %rdi
callq 0x7520
jmp 0x72299
movq -0x180(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x9c50
jmp 0x722ae
movq -0x180(%rbp), %rdi
movb $0x0, -0x10a(%rbp)
leaq 0x13bb15(%rip), %rsi    # 0x1addd8
leaq -0x6863a(%rip), %rdx    # 0x9c90
callq 0x7610
jmp 0x7243f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x72306
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x7708
leaq -0x109(%rbp), %rdi
callq 0x73d0
testb $0x1, -0x10a(%rbp)
jne 0x7231d
jmp 0x72329
movq -0x180(%rbp), %rdi
callq 0x72c0
jmp 0x72433
movb $0x1, -0x132(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x190(%rbp)
leaq -0x131(%rbp), %rdi
movq %rdi, -0x188(%rbp)
callq 0x7650
movq -0x188(%rbp), %rdx
leaq 0xd01ee(%rip), %rsi     # 0x142555
leaq -0x130(%rbp), %rdi
callq 0x7520
jmp 0x72375
movq -0x190(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0x9c50
jmp 0x7238a
movq -0x190(%rbp), %rdi
movb $0x0, -0x132(%rbp)
leaq 0x13ba39(%rip), %rsi    # 0x1addd8
leaq -0x68716(%rip), %rdx    # 0x9c90
callq 0x7610
jmp 0x7243f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x723e2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x7708
leaq -0x131(%rbp), %rdi
callq 0x73d0
testb $0x1, -0x132(%rbp)
jne 0x723f9
jmp 0x72405
movq -0x190(%rbp), %rdi
callq 0x72c0
jmp 0x72433
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdi
movl -0x14(%rbp), %edx
movq (%rsi), %rax
movl $0x1, %ecx
callq *0x38(%rax)
movq -0x148(%rbp), %rax
addq $0x190, %rsp            # imm = 0x190
popq %rbp
retq
movq -0x90(%rbp), %rdi
callq 0x7640
nop