avr-llvm / llvm

[MERGED UPSTREAM] AVR backend for the LLVM compiler library
220 stars 21 forks source link

fatal error: error in backend: expected relocatable expression #63

Closed 4ntoine closed 9 years ago

4ntoine commented 9 years ago
./clang -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DARDUINO=10600 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR  -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/variants/standard -I/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include --target=avr /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/WInterrupts.c -o /tmp/arduino_test1/WInterrupts.c.o
In file included from /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/WInterrupts.c:31:
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/stdio.h:724:12: warning: 
      declaration of built-in function 'fprintf' requires inclusion of the header <stdio.h>
      [-Wbuiltin-requires-header]
extern int      fprintf(FILE *__stream, const char *__fmt, ...);
                ^
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/stdio.h:875:12: warning: 
      declaration of built-in function 'vfscanf' requires inclusion of the header <stdio.h>
      [-Wbuiltin-requires-header]
extern int      vfscanf(FILE *__stream, const char *__fmt, va_list __ap);
                ^
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/stdio.h:888:12: warning: 
      declaration of built-in function 'fscanf' requires inclusion of the header <stdio.h>
      [-Wbuiltin-requires-header]
extern int      fscanf(FILE *__stream, const char *__fmt, ...);
                ^
fatal error: error in backend: expected relocatable expression
4ntoine commented 9 years ago

WInterrupts.c:

/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
  Part of the Wiring project - http://wiring.uniandes.edu.co

  Copyright (c) 2004-05 Hernando Barragan

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA

  Modified 24 November 2006 by David A. Mellis
  Modified 1 August 2010 by Mark Sproul
*/

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>

#include "wiring_private.h"

static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
// volatile static voidFuncPtr twiIntFunc;

void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
  if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
    intFunc[interruptNum] = userFunc;

    // Configure the interrupt mode (trigger on low input, any change, rising
    // edge, or falling edge).  The mode constants were chosen to correspond
    // to the configuration bits in the hardware register, so we simply shift
    // the mode into place.

    // Enable the interrupt.

    switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
    // I hate doing this, but the register assignment differs between the 1280/2560
    // and the 32U4.  Since avrlib defines registers PCMSK1 and PCMSK2 that aren't 
    // even present on the 32U4 this is the only way to distinguish between them.
    case 0:
    EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
    EIMSK |= (1<<INT0);
    break;
    case 1:
    EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
    EIMSK |= (1<<INT1);
    break;  
    case 2:
        EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
        EIMSK |= (1<<INT2);
        break;
    case 3:
        EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
        EIMSK |= (1<<INT3);
        break;
    case 4:
        EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
        EIMSK |= (1<<INT6);
        break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
    case 2:
      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      EIMSK |= (1 << INT0);
      break;
    case 3:
      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      EIMSK |= (1 << INT1);
      break;
    case 4:
      EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      EIMSK |= (1 << INT2);
      break;
    case 5:
      EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
      EIMSK |= (1 << INT3);
      break;
    case 0:
      EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
      EIMSK |= (1 << INT4);
      break;
    case 1:
      EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
      EIMSK |= (1 << INT5);
      break;
    case 6:
      EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
      EIMSK |= (1 << INT6);
      break;
    case 7:
      EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
      EIMSK |= (1 << INT7);
      break;
#else       
    case 0:
    #if defined(EICRA) && defined(ISC00) && defined(EIMSK)
      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      EIMSK |= (1 << INT0);
    #elif defined(MCUCR) && defined(ISC00) && defined(GICR)
      MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      GICR |= (1 << INT0);
    #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
      MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
      GIMSK |= (1 << INT0);
    #else
      #error attachInterrupt not finished for this CPU (case 0)
    #endif
      break;

    case 1:
    #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      EIMSK |= (1 << INT1);
    #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
      MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      GICR |= (1 << INT1);
    #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
      MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
      GIMSK |= (1 << INT1);
    #else
      #warning attachInterrupt may need some more work for this cpu (case 1)
    #endif
      break;

    case 2:
    #if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
      EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      EIMSK |= (1 << INT2);
    #elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
      MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      GICR |= (1 << INT2);
    #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
      MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
      GIMSK |= (1 << INT2);
    #endif
      break;
#endif
    }
  }
}

void detachInterrupt(uint8_t interruptNum) {
  if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
    // Disable the interrupt.  (We can't assume that interruptNum is equal
    // to the number of the EIMSK bit to clear, as this isn't true on the 
    // ATmega8.  There, INT0 is 6 and INT1 is 7.)
    switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
    case 0:
        EIMSK &= ~(1<<INT0);
        break;
    case 1:
        EIMSK &= ~(1<<INT1);
        break;
    case 2:
        EIMSK &= ~(1<<INT2);
        break;
    case 3:
        EIMSK &= ~(1<<INT3);
        break;  
    case 4:
        EIMSK &= ~(1<<INT6);
        break;  
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
    case 2:
      EIMSK &= ~(1 << INT0);
      break;
    case 3:
      EIMSK &= ~(1 << INT1);
      break;
    case 4:
      EIMSK &= ~(1 << INT2);
      break;
    case 5:
      EIMSK &= ~(1 << INT3);
      break;
    case 0:
      EIMSK &= ~(1 << INT4);
      break;
    case 1:
      EIMSK &= ~(1 << INT5);
      break;
    case 6:
      EIMSK &= ~(1 << INT6);
      break;
    case 7:
      EIMSK &= ~(1 << INT7);
      break;
#else
    case 0:
    #if defined(EIMSK) && defined(INT0)
      EIMSK &= ~(1 << INT0);
    #elif defined(GICR) && defined(ISC00)
      GICR &= ~(1 << INT0); // atmega32
    #elif defined(GIMSK) && defined(INT0)
      GIMSK &= ~(1 << INT0);
    #else
      #error detachInterrupt not finished for this cpu
    #endif
      break;

    case 1:
    #if defined(EIMSK) && defined(INT1)
      EIMSK &= ~(1 << INT1);
    #elif defined(GICR) && defined(INT1)
      GICR &= ~(1 << INT1); // atmega32
    #elif defined(GIMSK) && defined(INT1)
      GIMSK &= ~(1 << INT1);
    #else
      #warning detachInterrupt may need some more work for this cpu (case 1)
    #endif
      break;
#endif
    }

    intFunc[interruptNum] = 0;
  }
}

/*
void attachInterruptTwi(void (*userFunc)(void) ) {
  twiIntFunc = userFunc;
}
*/

#if defined(__AVR_ATmega32U4__)
ISR(INT0_vect) {
    if(intFunc[EXTERNAL_INT_0])
        intFunc[EXTERNAL_INT_0]();
}

ISR(INT1_vect) {
    if(intFunc[EXTERNAL_INT_1])
        intFunc[EXTERNAL_INT_1]();
}

ISR(INT2_vect) {
    if(intFunc[EXTERNAL_INT_2])
        intFunc[EXTERNAL_INT_2]();
}

ISR(INT3_vect) {
    if(intFunc[EXTERNAL_INT_3])
        intFunc[EXTERNAL_INT_3]();
}

ISR(INT6_vect) {
    if(intFunc[EXTERNAL_INT_4])
        intFunc[EXTERNAL_INT_4]();
}

#elif defined(EICRA) && defined(EICRB)

ISR(INT0_vect) {
  if(intFunc[EXTERNAL_INT_2])
    intFunc[EXTERNAL_INT_2]();
}

ISR(INT1_vect) {
  if(intFunc[EXTERNAL_INT_3])
    intFunc[EXTERNAL_INT_3]();
}

ISR(INT2_vect) {
  if(intFunc[EXTERNAL_INT_4])
    intFunc[EXTERNAL_INT_4]();
}

ISR(INT3_vect) {
  if(intFunc[EXTERNAL_INT_5])
    intFunc[EXTERNAL_INT_5]();
}

ISR(INT4_vect) {
  if(intFunc[EXTERNAL_INT_0])
    intFunc[EXTERNAL_INT_0]();
}

ISR(INT5_vect) {
  if(intFunc[EXTERNAL_INT_1])
    intFunc[EXTERNAL_INT_1]();
}

ISR(INT6_vect) {
  if(intFunc[EXTERNAL_INT_6])
    intFunc[EXTERNAL_INT_6]();
}

ISR(INT7_vect) {
  if(intFunc[EXTERNAL_INT_7])
    intFunc[EXTERNAL_INT_7]();
}

#else

ISR(INT0_vect) {
  if(intFunc[EXTERNAL_INT_0])
    intFunc[EXTERNAL_INT_0]();
}

ISR(INT1_vect) {
  if(intFunc[EXTERNAL_INT_1])
    intFunc[EXTERNAL_INT_1]();
}

#if defined(EICRA) && defined(ISC20)
ISR(INT2_vect) {
  if(intFunc[EXTERNAL_INT_2])
    intFunc[EXTERNAL_INT_2]();
}
#endif

#endif

/*
ISR(TWI_vect) {
  if(twiIntFunc)
    twiIntFunc();
}
*/
dylanmckay commented 9 years ago

Reduced testcases:

WInterrupts.ll:

llc WInterrupts.ll -mcpu=atmega328p -filetype=obj
; ModuleID = '/usr/share/arduino/hardware/arduino/avr/cores/arduino/WInterrupts.c'
target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-i64:8:8-f32:8:8-f64:8:8-n8"
target triple = "avr"

@intFunc = internal global [2 x void ()*] zeroinitializer, align 2
@llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @__vector_1 to i8*), i8* bitcast (void ()* @__vector_2 to i8*)], section "llvm.metadata"

; Function Attrs: nounwind optsize
define void @attachInterrupt(i8 zeroext %interruptNum, void ()* %userFunc, i16 %mode) #0 {
entry:
  tail call void @llvm.dbg.value(metadata i8 %interruptNum, i64 0, metadata !18, metadata !39), !dbg !40
  tail call void @llvm.dbg.value(metadata void ()* %userFunc, i64 0, metadata !19, metadata !39), !dbg !41
  tail call void @llvm.dbg.value(metadata i16 %mode, i64 0, metadata !20, metadata !39), !dbg !42
  %cmp = icmp ult i8 %interruptNum, 2, !dbg !43
  br i1 %cmp, label %if.then, label %if.end, !dbg !45

if.then:                                          ; preds = %entry
  %conv = zext i8 %interruptNum to i16, !dbg !46
  %arrayidx = getelementptr inbounds [2 x void ()*], [2 x void ()*]* @intFunc, i16 0, i16 %conv, !dbg !47
  store volatile void ()* %userFunc, void ()** %arrayidx, align 2, !dbg !49, !tbaa !50
  switch i8 %interruptNum, label %if.end [
    i8 0, label %sw.bb
    i8 1, label %sw.bb.8
  ], !dbg !54

sw.bb:                                            ; preds = %if.then
  %0 = load volatile i8, i8* inttoptr (i16 105 to i8*), align 1, !dbg !55, !tbaa !57
  %conv3 = zext i8 %0 to i16, !dbg !55
  %and = and i16 %conv3, 252, !dbg !58
  %or = or i16 %and, %mode, !dbg !59
  %conv4 = trunc i16 %or to i8, !dbg !60
  store volatile i8 %conv4, i8* inttoptr (i16 105 to i8*), align 1, !dbg !61, !tbaa !57
  %1 = load volatile i8, i8* inttoptr (i16 61 to i8*), align 1, !dbg !62, !tbaa !57
  %or6 = or i8 %1, 1, !dbg !62
  store volatile i8 %or6, i8* inttoptr (i16 61 to i8*), align 1, !dbg !62, !tbaa !57
  br label %if.end, !dbg !63

sw.bb.8:                                          ; preds = %if.then
  %2 = load volatile i8, i8* inttoptr (i16 105 to i8*), align 1, !dbg !64, !tbaa !57
  %conv9 = zext i8 %2 to i16, !dbg !64
  %and10 = and i16 %conv9, 243, !dbg !65
  %shl11 = shl i16 %mode, 2, !dbg !66
  %or12 = or i16 %and10, %shl11, !dbg !67
  %conv13 = trunc i16 %or12 to i8, !dbg !68
  store volatile i8 %conv13, i8* inttoptr (i16 105 to i8*), align 1, !dbg !69, !tbaa !57
  %3 = load volatile i8, i8* inttoptr (i16 61 to i8*), align 1, !dbg !70, !tbaa !57
  %or15 = or i8 %3, 2, !dbg !70
  store volatile i8 %or15, i8* inttoptr (i16 61 to i8*), align 1, !dbg !70, !tbaa !57
  br label %if.end, !dbg !71

if.end:                                           ; preds = %sw.bb, %sw.bb.8, %if.then, %entry
  ret void, !dbg !72
}

; Function Attrs: nounwind optsize
define void @detachInterrupt(i8 zeroext %interruptNum) #0 {
entry:
  tail call void @llvm.dbg.value(metadata i8 %interruptNum, i64 0, metadata !25, metadata !39), !dbg !73
  %conv = zext i8 %interruptNum to i16, !dbg !74
  %cmp = icmp ult i8 %interruptNum, 2, !dbg !76
  br i1 %cmp, label %if.then, label %if.end, !dbg !77

if.then:                                          ; preds = %entry
  switch i8 %interruptNum, label %sw.epilog [
    i8 0, label %sw.bb
    i8 1, label %sw.bb.5
  ], !dbg !78

sw.bb:                                            ; preds = %if.then
  %0 = load volatile i8, i8* inttoptr (i16 61 to i8*), align 1, !dbg !80, !tbaa !57
  %and = and i8 %0, -2, !dbg !80
  store volatile i8 %and, i8* inttoptr (i16 61 to i8*), align 1, !dbg !80, !tbaa !57
  br label %sw.epilog, !dbg !82

sw.bb.5:                                          ; preds = %if.then
  %1 = load volatile i8, i8* inttoptr (i16 61 to i8*), align 1, !dbg !83, !tbaa !57
  %and7 = and i8 %1, -3, !dbg !83
  store volatile i8 %and7, i8* inttoptr (i16 61 to i8*), align 1, !dbg !83, !tbaa !57
  br label %sw.epilog, !dbg !84

sw.epilog:                                        ; preds = %if.then, %sw.bb.5, %sw.bb
  %arrayidx = getelementptr inbounds [2 x void ()*], [2 x void ()*]* @intFunc, i16 0, i16 %conv, !dbg !85
  store volatile void ()* null, void ()** %arrayidx, align 2, !dbg !86, !tbaa !50
  br label %if.end, !dbg !87

if.end:                                           ; preds = %sw.epilog, %entry
  ret void, !dbg !88
}

; Function Attrs: noinline nounwind optsize
define avr_signalcc  void @__vector_1() #1 {
entry:
  %0 = load volatile void ()*, void ()** getelementptr inbounds ([2 x void ()*], [2 x void ()*]* @intFunc, i16 0, i16 0), align 2, !dbg !89, !tbaa !50
  %tobool = icmp eq void ()* %0, null, !dbg !89
  br i1 %tobool, label %if.end, label %if.then, !dbg !91

if.then:                                          ; preds = %entry
  %1 = load volatile void ()*, void ()** getelementptr inbounds ([2 x void ()*], [2 x void ()*]* @intFunc, i16 0, i16 0), align 2, !dbg !92, !tbaa !50
  tail call void %1() #3, !dbg !92
  br label %if.end, !dbg !92

if.end:                                           ; preds = %entry, %if.then
  ret void, !dbg !93
}

; Function Attrs: noinline nounwind optsize
define avr_signalcc  void @__vector_2() #1 {
entry:
  %0 = load volatile void ()*, void ()** getelementptr inbounds ([2 x void ()*], [2 x void ()*]* @intFunc, i16 0, i16 1), align 2, !dbg !94, !tbaa !50
  %tobool = icmp eq void ()* %0, null, !dbg !94
  br i1 %tobool, label %if.end, label %if.then, !dbg !96

if.then:                                          ; preds = %entry
  %1 = load volatile void ()*, void ()** getelementptr inbounds ([2 x void ()*], [2 x void ()*]* @intFunc, i16 0, i16 1), align 2, !dbg !97, !tbaa !50
  tail call void %1() #3, !dbg !97
  br label %if.end, !dbg !97

if.end:                                           ; preds = %entry, %if.then
  ret void, !dbg !98
}

; Function Attrs: nounwind readnone
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2

attributes #0 = { nounwind optsize "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="atmega328p" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { noinline nounwind optsize "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="atmega328p" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind readnone }
attributes #3 = { nounwind optsize }

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!36, !37}
!llvm.ident = !{!38}

!0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.7.0 (https://github.com/llvm-mirror/clang.git aebd4f6d15e44635ecc7338d4454389c4573bc2b) (https://github.com/llvm-mirror/llvm.git 2f1e7fe1e133874beba11f82834ce6cbb995510b)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3, subprograms: !9, globals: !28, imports: !2)
!1 = !DIFile(filename: "/usr/share/arduino/hardware/arduino/avr/cores/arduino/WInterrupts.c", directory: "/home/dylan/projects/builds/avr-llvm/llvm/bin")
!2 = !{}
!3 = !{!4}
!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 16, align: 16)
!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6)
!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint8_t", file: !7, line: 123, baseType: !8)
!7 = !DIFile(filename: "/usr/avr/include/stdint.h", directory: "/home/dylan/projects/builds/avr-llvm/llvm/bin")
!8 = !DIBasicType(name: "unsigned char", size: 8, align: 8, encoding: DW_ATE_unsigned_char)
!9 = !{!10, !21, !26, !27}
!10 = !DISubprogram(name: "attachInterrupt", scope: !1, file: !1, line: 38, type: !11, isLocal: false, isDefinition: true, scopeLine: 38, flags: DIFlagPrototyped, isOptimized: true, function: void (i8, void ()*, i16)* @attachInterrupt, variables: !17)
!11 = !DISubroutineType(types: !12)
!12 = !{null, !6, !13, !16}
!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 16, align: 16)
!14 = !DISubroutineType(types: !15)
!15 = !{null}
!16 = !DIBasicType(name: "int", size: 16, align: 16, encoding: DW_ATE_signed)
!17 = !{!18, !19, !20}
!18 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "interruptNum", arg: 1, scope: !10, file: !1, line: 38, type: !6)
!19 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "userFunc", arg: 2, scope: !10, file: !1, line: 38, type: !13)
!20 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "mode", arg: 3, scope: !10, file: !1, line: 38, type: !16)
!21 = !DISubprogram(name: "detachInterrupt", scope: !1, file: !1, line: 155, type: !22, isLocal: false, isDefinition: true, scopeLine: 155, flags: DIFlagPrototyped, isOptimized: true, function: void (i8)* @detachInterrupt, variables: !24)
!22 = !DISubroutineType(types: !23)
!23 = !{null, !6}
!24 = !{!25}
!25 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "interruptNum", arg: 1, scope: !21, file: !1, line: 155, type: !6)
!26 = !DISubprogram(name: "__vector_1", scope: !1, file: !1, line: 309, type: !14, isLocal: false, isDefinition: true, scopeLine: 309, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @__vector_1, variables: !2)
!27 = !DISubprogram(name: "__vector_2", scope: !1, file: !1, line: 314, type: !14, isLocal: false, isDefinition: true, scopeLine: 314, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @__vector_2, variables: !2)
!28 = !{!29}
!29 = !DIGlobalVariable(name: "intFunc", scope: !0, file: !1, line: 35, type: !30, isLocal: true, isDefinition: true, variable: [2 x void ()*]* @intFunc)
!30 = !DICompositeType(tag: DW_TAG_array_type, baseType: !31, size: 32, align: 16, elements: !34)
!31 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !32)
!32 = !DIDerivedType(tag: DW_TAG_typedef, name: "voidFuncPtr", file: !33, line: 65, baseType: !13)
!33 = !DIFile(filename: "/usr/share/arduino/hardware/arduino/avr/cores/arduino/wiring_private.h", directory: "/home/dylan/projects/builds/avr-llvm/llvm/bin")
!34 = !{!35}
!35 = !DISubrange(count: 2)
!36 = !{i32 2, !"Dwarf Version", i32 4}
!37 = !{i32 2, !"Debug Info Version", i32 3}
!38 = !{!"clang version 3.7.0 (https://github.com/llvm-mirror/clang.git aebd4f6d15e44635ecc7338d4454389c4573bc2b) (https://github.com/llvm-mirror/llvm.git 2f1e7fe1e133874beba11f82834ce6cbb995510b)"}
!39 = !DIExpression()
!40 = !DILocation(line: 38, column: 30, scope: !10)
!41 = !DILocation(line: 38, column: 51, scope: !10)
!42 = !DILocation(line: 38, column: 72, scope: !10)
!43 = !DILocation(line: 39, column: 19, scope: !44)
!44 = distinct !DILexicalBlock(scope: !10, file: !1, line: 39, column: 6)
!45 = !DILocation(line: 39, column: 6, scope: !10)
!46 = !DILocation(line: 39, column: 6, scope: !44)
!47 = !DILocation(line: 40, column: 5, scope: !48)
!48 = distinct !DILexicalBlock(scope: !44, file: !1, line: 39, column: 46)
!49 = !DILocation(line: 40, column: 27, scope: !48)
!50 = !{!51, !51, i64 0}
!51 = !{!"any pointer", !52, i64 0}
!52 = !{!"omnipotent char", !53, i64 0}
!53 = !{!"Simple C/C++ TBAA"}
!54 = !DILocation(line: 49, column: 5, scope: !48)
!55 = !DILocation(line: 110, column: 16, scope: !56)
!56 = distinct !DILexicalBlock(scope: !48, file: !1, line: 49, column: 27)
!57 = !{!52, !52, i64 0}
!58 = !DILocation(line: 110, column: 22, scope: !56)
!59 = !DILocation(line: 110, column: 56, scope: !56)
!60 = !DILocation(line: 110, column: 15, scope: !56)
!61 = !DILocation(line: 110, column: 13, scope: !56)
!62 = !DILocation(line: 111, column: 13, scope: !56)
!63 = !DILocation(line: 121, column: 7, scope: !56)
!64 = !DILocation(line: 125, column: 16, scope: !56)
!65 = !DILocation(line: 125, column: 22, scope: !56)
!66 = !DILocation(line: 125, column: 64, scope: !56)
!67 = !DILocation(line: 125, column: 56, scope: !56)
!68 = !DILocation(line: 125, column: 15, scope: !56)
!69 = !DILocation(line: 125, column: 13, scope: !56)
!70 = !DILocation(line: 126, column: 13, scope: !56)
!71 = !DILocation(line: 136, column: 7, scope: !56)
!72 = !DILocation(line: 153, column: 1, scope: !10)
!73 = !DILocation(line: 155, column: 30, scope: !21)
!74 = !DILocation(line: 156, column: 6, scope: !75)
!75 = distinct !DILexicalBlock(scope: !21, file: !1, line: 156, column: 6)
!76 = !DILocation(line: 156, column: 19, scope: !75)
!77 = !DILocation(line: 156, column: 6, scope: !21)
!78 = !DILocation(line: 160, column: 5, scope: !79)
!79 = distinct !DILexicalBlock(scope: !75, file: !1, line: 156, column: 46)
!80 = !DILocation(line: 205, column: 13, scope: !81)
!81 = distinct !DILexicalBlock(scope: !79, file: !1, line: 160, column: 27)
!82 = !DILocation(line: 213, column: 7, scope: !81)
!83 = !DILocation(line: 217, column: 13, scope: !81)
!84 = !DILocation(line: 225, column: 7, scope: !81)
!85 = !DILocation(line: 229, column: 5, scope: !79)
!86 = !DILocation(line: 229, column: 27, scope: !79)
!87 = !DILocation(line: 230, column: 3, scope: !79)
!88 = !DILocation(line: 231, column: 1, scope: !21)
!89 = !DILocation(line: 310, column: 6, scope: !90)
!90 = distinct !DILexicalBlock(scope: !26, file: !1, line: 310, column: 6)
!91 = !DILocation(line: 310, column: 6, scope: !26)
!92 = !DILocation(line: 311, column: 5, scope: !90)
!93 = !DILocation(line: 312, column: 1, scope: !26)
!94 = !DILocation(line: 315, column: 6, scope: !95)
!95 = distinct !DILexicalBlock(scope: !27, file: !1, line: 315, column: 6)
!96 = !DILocation(line: 315, column: 6, scope: !27)
!97 = !DILocation(line: 316, column: 5, scope: !95)
!98 = !DILocation(line: 317, column: 1, scope: !27)

WInterrupts.s:

llvm-mc WInterrupts.s --triple avr -mcpu=atmega328p -filetype=obj
    .text
    .file   "WInterrupts.ll"
    .globl  attachInterrupt
    .align  2
    .type   attachInterrupt,@function
attachInterrupt:                        ; @attachInterrupt
; BB#0:                                 ; %entry
    ;DEBUG_VALUE: attachInterrupt:interruptNum <- R24
    ;DEBUG_VALUE: attachInterrupt:userFunc <- R23R22
    ;DEBUG_VALUE: attachInterrupt:mode <- R21R20
    ldi r25, 2
    cp  r24, r25
    brsh    LBB0_5
; BB#1:                                 ; %if.then
    ;DEBUG_VALUE: attachInterrupt:interruptNum <- R24
    ;DEBUG_VALUE: attachInterrupt:userFunc <- R23R22
    ;DEBUG_VALUE: attachInterrupt:mode <- R21R20
    mov r30, r24
    eor r31, r31
    lsl r30
    rol r31
    subi    r30, lo8(-intFunc)
    sbci    r31, hi8(-intFunc)
    st  Z, r22
    std Z+1, r23
    ldi r25, 1
    cp  r24, r25
    brne    LBB0_3
; BB#2:                                 ; %sw.bb.8
    ;DEBUG_VALUE: attachInterrupt:mode <- R21R20
    lds r24, 105
    andi    r24, 243
    andi    r25, 0
    lsl r20
    rol r21
    lsl r20
    rol r21
    or  r20, r24
    or  r21, r25
    sts 105, r20
    sbi 29, 1
    rjmp    LBB0_5
LBB0_3:                                 ; %if.then
    ;DEBUG_VALUE: attachInterrupt:interruptNum <- R24
    ;DEBUG_VALUE: attachInterrupt:mode <- R21R20
    ldi r25, 0
    cp  r24, r25
    brne    LBB0_5
; BB#4:                                 ; %sw.bb
    ;DEBUG_VALUE: attachInterrupt:mode <- R21R20
    lds r24, 105
    andi    r24, 252
    andi    r25, 0
    or  r24, r20
    or  r25, r21
    sts 105, r24
    sbi 29, 0
    ret
LBB0_5:                                 ; %if.end
    ret
.Lfunc_end0:
    .size   attachInterrupt, .Lfunc_end0-attachInterrupt

    .globl  detachInterrupt
    .align  2
    .type   detachInterrupt,@function
detachInterrupt:                        ; @detachInterrupt
; BB#0:                                 ; %entry
    ;DEBUG_VALUE: detachInterrupt:interruptNum <- R24
    ldi r25, 2
    cp  r24, r25
    brsh    LBB1_6
; BB#1:                                 ; %if.then
    ;DEBUG_VALUE: detachInterrupt:interruptNum <- R24
    mov r30, r24
    eor r31, r31
    ldi r25, 1
    cp  r24, r25
    brne    LBB1_3
; BB#2:                                 ; %sw.bb.5
    cbi 29, 1
    rjmp    LBB1_5
LBB1_3:                                 ; %if.then
    ;DEBUG_VALUE: detachInterrupt:interruptNum <- R24
    ldi r25, 0
    cp  r24, r25
    brne    LBB1_5
; BB#4:                                 ; %sw.bb
    cbi 29, 0
LBB1_5:                                 ; %sw.epilog
    lsl r30
    rol r31
    subi    r30, lo8(-intFunc)
    sbci    r31, hi8(-intFunc)
    ldi r24, 0
    ldi r25, 0
    st  Z, r24
    std Z+1, r25
LBB1_6:                                 ; %if.end
    ret
.Lfunc_end1:
    .size   detachInterrupt, .Lfunc_end1-detachInterrupt

    .globl  __vector_1
    .align  2
    .type   __vector_1,@function
__vector_1:                             ; @__vector_1
; BB#0:                                 ; %entry
    push    r0
    push    r1
    in  r0, 63
    push    r0
    push    r0
    push    r1
    push    r18
    push    r19
    push    r20
    push    r21
    push    r22
    push    r23
    push    r24
    push    r25
    push    r26
    push    r27
    push    r30
    push    r31
    ldi r24, 0
    ldi r25, 0
    lds r18, intFunc
    lds r19, intFunc+1
    cp  r18, r24
    cpc r19, r25
    breq    LBB2_2
; BB#1:                                 ; %if.then
    lds r30, intFunc
    lds r31, intFunc+1
    icall
LBB2_2:                                 ; %if.end
    pop r31
    pop r30
    pop r27
    pop r26
    pop r25
    pop r24
    pop r23
    pop r22
    pop r21
    pop r20
    pop r19
    pop r18
    pop r1
    pop r0
    pop r0
    out 63, r0
    pop r1
    pop r0
    reti
.Lfunc_end2:
    .size   __vector_1, .Lfunc_end2-__vector_1

    .globl  __vector_2
    .align  2
    .type   __vector_2,@function
__vector_2:                             ; @__vector_2
; BB#0:                                 ; %entry
    push    r0
    push    r1
    in  r0, 63
    push    r0
    push    r0
    push    r1
    push    r18
    push    r19
    push    r20
    push    r21
    push    r22
    push    r23
    push    r24
    push    r25
    push    r26
    push    r27
    push    r30
    push    r31
    ldi r24, 0
    ldi r25, 0
    lds r18, intFunc+2
    lds r19, intFunc+3
    cp  r18, r24
    cpc r19, r25
    breq    LBB3_2
; BB#1:                                 ; %if.then
    lds r30, intFunc+2
    lds r31, intFunc+3
    icall
LBB3_2:                                 ; %if.end
    pop r31
    pop r30
    pop r27
    pop r26
    pop r25
    pop r24
    pop r23
    pop r22
    pop r21
    pop r20
    pop r19
    pop r18
    pop r1
    pop r0
    pop r0
    out 63, r0
    pop r1
    pop r0
    reti
.Lfunc_end3:
    .size   __vector_2, .Lfunc_end3-__vector_2

    .type   intFunc,@object         ; @intFunc
    .local  intFunc
    .comm   intFunc,4,2
dylanmckay commented 9 years ago

This is caused because AVRMCExpr::evaluateAsRelocatableImpl doesn't handle the case where the hi8(..), lo8(..) fixups have non-absolute immediates as targets (i.e. a label as a target).

Reduced, reduced test case:

llvm-mc -arch=avr -mcpu=atmega328p -filetype=obj
sbci  r31, lo8(main)
agnat commented 9 years ago

Hehe, I'm already on it. Here is my test case:

foo: ldi r24, lo8(foo)

The whole fixup-relocation-expression-business seems a bit out of whack. Note, that this is probably (partly) my doing, since I beefed up AVRMCExpr a bit, left a dangling TODO... yadda yadda

dylanmckay commented 9 years ago

Your testcase is nice, but it could use some work :)

I have strong doubts that you had anything to do with this bug due to how old it is.

4ntoine commented 9 years ago

still having the issue:

MBA-Anton:bin asmirnov$ ./clang --version
clang version 3.7.0 (https://github.com/avr-llvm/clang.git aebd4f6d15e44635ecc7338d4454389c4573bc2b) (llvm/llvm 9c7c5212863ed8b06323ad07fa84bad29ff051f8)
Target: x86_64-apple-darwin14.3.0
Thread model: posix
MBA-Anton:bin asmirnov$ ./clang -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DARDUINO=10600 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR  -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/variants/standard -I/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include --target=avr /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/WInterrupts.c -o /tmp/arduino_test1/WInterrupts.c.o
In file included from /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/WInterrupts.c:31:
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/stdio.h:724:12: warning: 
      declaration of built-in function 'fprintf' requires inclusion of the header <stdio.h>
      [-Wbuiltin-requires-header]
extern int      fprintf(FILE *__stream, const char *__fmt, ...);
                ^
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/stdio.h:875:12: warning: 
      declaration of built-in function 'vfscanf' requires inclusion of the header <stdio.h>
      [-Wbuiltin-requires-header]
extern int      vfscanf(FILE *__stream, const char *__fmt, va_list __ap);
                ^
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/stdio.h:888:12: warning: 
      declaration of built-in function 'fscanf' requires inclusion of the header <stdio.h>
      [-Wbuiltin-requires-header]
extern int      fscanf(FILE *__stream, const char *__fmt, ...);
                ^
fatal error: error in backend: expected relocatable expression
dylanmckay commented 9 years ago

Can you try llvm-mc --triple avr -mcpu=atmega328p -filetype=obj and type ldi r24, lo8(main) and then Enter Ctrl+D Enter? does this succeed?