// File: /workspace/github_c_makefile_star2_O2/ejunjsh[P]mycc/types.c
// Function: modify_type
struct ASTnode *modify_type(struct ASTnode *tree, int rtype,
			    struct symtable *rctype, int op) {
  int ltype;
  int lsize, rsize;

  ltype = tree->type;

  // 对于A_LOGOR 和 A_LOGAND， 这两个类型必须是整型或者指针类型
  if (op==A_LOGOR || op==A_LOGAND) {
    if (!inttype(ltype) && !ptrtype(ltype))
      return(NULL);
      //TODO:？？
    if (!inttype(ltype) && !ptrtype(rtype))
      return(NULL);
    return (tree);
  }

  // TODO:还没有实现复合结构
  if (ltype == P_STRUCT || ltype == P_UNION)
    fatal("Don't know how to do this yet");
  if (rtype == P_STRUCT || rtype == P_UNION)
    fatal("Don't know how to do this yet");

  // 都是整型
  if (inttype(ltype) && inttype(rtype)) {

    // 类型一样，直接返回
    if (ltype == rtype)
      return (tree);

    // 获得类型大小
    lsize = typesize(ltype, NULL);
    rsize = typesize(rtype, NULL);

    // 当前类型大小大于rtype类型，不兼容，我们不能截断
    if (lsize > rsize)
      return (NULL);

    // 如果当前小于rtype，增容
    if (rsize > lsize)
      return (mkastunary(A_WIDEN, rtype, NULL, tree, NULL, 0));
  }

  // 对于指针
  if (ptrtype(ltype) && ptrtype(rtype)) {
    // 指针可以比较
    if (op >= A_EQ && op <= A_GE)
      return (tree);

    // 对于非二元操作，相同类型，可以直接返回
    // 或者当前类型是一个`void *`类型
    if (op == 0 && (ltype == rtype || ltype == pointer_to(P_VOID)))
      return (tree);
  }

  // 只有在加减操作才进行倍数操作
  // 例如：int* p; int* a=p+1,实际上a的值是p的值加上4，4是整型类型大小，所以4是要作为倍数来修改原来的树
  if (op == A_ADD || op == A_SUBTRACT ||
      op == A_ASPLUS || op == A_ASMINUS) {

    // 当前是整型，rtype是指针类型，同时它的原来类型大小是大于一
    // 就要把当前类型倍数改成rtype的原来类型的大小
    if (inttype(ltype) && ptrtype(rtype)) {
      rsize = genprimsize(value_at(rtype));
      if (rsize > 1)
	    return (mkastunary(A_SCALE, rtype, rctype, tree, NULL, rsize)); // 包装原来那棵tree
      else
	    return (tree);		// 大小为一，不用修改倍数，直接返回
    }
  }

  // 到这里，代表类型不兼容
  return (NULL);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %esi, %r14d
movq %rdi, %rbx
movl 0x8(%rdi), %r13d
movl %ecx, %eax
andl $-0x2, %eax
cmpl $0x8, %eax
jne 0x8813
testb $0xf, %r13b
sete %al
leal -0x41(%r13), %ecx
cmpl $-0x21, %ecx
setae %cl
testb %cl, %al
jne 0x88d1
testb $0xf, %r13b
sete %al
testb $0xf, %r14b
sete %cl
orb %al, %cl
jne 0x88cf
jmp 0x88d1
movl %ecx, %r12d
movq %rdx, -0x38(%rbp)
cmpl $0x60, %r13d
je 0x8826
cmpl $0x50, %r13d
jne 0x8832
leaq 0x27e6(%rip), %rdi      # 0xb013
callq 0x6515
cmpl $0x60, %r14d
je 0x883e
cmpl $0x50, %r14d
jne 0x884a
leaq 0x27ce(%rip), %rdi      # 0xb013
callq 0x6515
testb $0xf, %r13b
setne %al
leal -0x41(%r13), %ecx
cmpl $-0x21, %ecx
setb %r15b
orb %al, %r15b
je 0x8898
testb $0xf, %r13b
sete %cl
testb $0xf, %r14b
sete %al
orb %al, %cl
jne 0x88b4
leal -0xd(%r12), %eax
cmpl $0x6, %eax
jb 0x88d1
testl %r12d, %r12d
jne 0x88cf
movq %rbx, %rax
xorl %ebx, %ebx
cmpl $0x11, %r13d
cmoveq %rax, %rbx
cmpl %r14d, %r13d
cmoveq %rax, %rbx
jmp 0x88d1
testb $0xf, %r14b
setne %al
leal -0x41(%r14), %ecx
cmpl $-0x21, %ecx
setb %cl
orb %al, %cl
je 0x88e3
testb $0xf, %r14b
sete %al
movq %rbx, %r13
xorl %ebx, %ebx
cmpl $0x16, %r12d
ja 0x88d1
movl $0x60000c, %ecx         # imm = 0x60000C
btl %r12d, %ecx
jae 0x88d1
orb %r15b, %al
je 0x8923
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl %r14d, %r13d
je 0x88d1
movq %rbx, -0x30(%rbp)
xorl %ebx, %ebx
movl %r13d, %edi
xorl %esi, %esi
callq 0x87a1
movl %eax, %r13d
movl %r14d, %edi
xorl %esi, %esi
callq 0x87a1
cmpl %eax, %r13d
jg 0x88d1
movq -0x30(%rbp), %rbx
jge 0x88ad
pushq $0x21
popq %rdi
movl %r14d, %esi
xorl %edx, %edx
movq %rbx, %rcx
xorl %r8d, %r8d
xorl %r9d, %r9d
jmp 0x894a
movl %r14d, %edi
callq 0x877b
movl %eax, %edi
callq 0x5da9
cmpl $0x2, %eax
jl 0x895d
pushq $0x26
popq %rdi
movl %r14d, %esi
movq -0x38(%rbp), %rdx
movq %r13, %rcx
xorl %r8d, %r8d
movl %eax, %r9d
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x81aa
movq %r13, %rbx
jmp 0x88d1