// File: /workspace/github_c_makefile_star2_O3/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
pushq %rax
movl %esi, %r14d
movq %rdi, %rbx
movl 0x8(%rdi), %r13d
movl %ecx, %eax
andl $-0x2, %eax
cmpl $0x8, %eax
jne 0x8f10
testb $0xf, %r13b
sete %al
leal -0x41(%r13), %ecx
cmpl $-0x21, %ecx
setae %cl
testb %cl, %al
jne 0x8ff4
testb $0xf, %r13b
sete %al
testb $0xf, %r14b
sete %cl
orb %al, %cl
je 0x8ff4
jmp 0x9011
movl %ecx, %r12d
movq %rdx, -0x30(%rbp)
cmpl $0x60, %r13d
je 0x8f23
cmpl $0x50, %r13d
jne 0x8f2f
leaq 0x30e9(%rip), %rdi      # 0xc013
callq 0x6937
cmpl $0x60, %r14d
je 0x8f3b
cmpl $0x50, %r14d
jne 0x8f47
leaq 0x30d1(%rip), %rdi      # 0xc013
callq 0x6937
testb $0xf, %r13b
setne %al
leal -0x41(%r13), %ecx
cmpl $-0x21, %ecx
setb %r15b
orb %al, %r15b
je 0x8f96
testb $0xf, %r13b
sete %al
testb $0xf, %r14b
sete %cl
orb %cl, %al
jne 0x8fb2
leal -0xd(%r12), %eax
cmpl $0x6, %eax
jb 0x8ff4
testl %r12d, %r12d
jne 0x9011
xorl %eax, %eax
cmpl $0x11, %r13d
cmoveq %rbx, %rax
cmpl %r14d, %r13d
cmoveq %rbx, %rax
jmp 0x9013
testb $0xf, %r14b
setne %al
leal -0x41(%r14), %ecx
cmpl $-0x21, %ecx
setb %cl
orb %al, %cl
je 0x8fef
testb $0xf, %r14b
sete %cl
xorl %eax, %eax
cmpl $0x16, %r12d
ja 0x9013
movl $0x60000c, %edx         # imm = 0x60000C
btl %r12d, %edx
jae 0x9013
orb %r15b, %cl
jne 0x9011
leal -0x1(%r14), %edi
callq 0x6231
cmpl $0x2, %eax
jl 0x8ff4
movl $0x26, %edi
movl %r14d, %esi
movq -0x30(%rbp), %rdx
movq %rbx, %rcx
xorl %r8d, %r8d
movl %eax, %r9d
jmp 0x9037
cmpl %r14d, %r13d
jne 0x8ff9
movq %rbx, %rax
jmp 0x9013
movl %r13d, %edi
callq 0x6231
movl %eax, %r13d
movl %r14d, %edi
callq 0x6231
cmpl %eax, %r13d
jle 0x9022
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jge 0x8fab
movl $0x21, %edi
movl %r14d, %esi
xorl %edx, %edx
movq %rbx, %rcx
xorl %r8d, %r8d
xorl %r9d, %r9d
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x88d3