Posted: April 23, 2009 by Datazygte, Inc - contribution by rscheckelhoff- at- fourcalorieservers dot-com
LLVM1 and Clang are words describing a potent duo that will soon be on the tips of many tongues.
The LLVM and Clang projects are being carried on at the University of Illinois, Urbana-Champaigne. The
LLVM (low level virtual machine) project is an attempt (mostly successful, already) to implement a
framework for many compiler flavors, providing both native code generation capability and
jit (just in time) intermediate code generation.
I decided to download the svn repository code and start a project to test the new compiler system.
The impetus for the project began when I realized that I was being sucked into a gpl-v3 world that
I didn't feel comfortable with.
Ostensibly, when LLVM/Clang is finished, it should provide a viable alternative compiler that is not encumbered by gplv3 licensing. (The UIUC license is a BSD-like license).
For the OS, I used (as is my custom) FreeBSD version 7.1-RELEASE. The process was started by downloading the code from the subversion repository:
pkg_add -rK subversion (because it was not on the system)
/usr/local/bin/svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
pkg_add -rK gmake (because it was not already on the system)
... I then changed to the newly created llvm source directory:
cd llvm
... and configured the build ...
./configure --prefix=/usr/local --enable-optimized
The --enable-optimized setting is highly recommended. I tried the compilation both ways, and found a large difference in
compile speed and executable size. The Debug build (without optimization) used 1.2Gb of disk space in the
llvm/Debug/bin and llvm/Debug/lib
directories. The optimized Release build created only a couple hundred megabytes of executable and library files in
the llvm/Release/bin and
llvm/Release/lib directories.
... I then executed gmake to compile and link the llvm executables:
gmake
When LLVM completed the compilation and linking processes, I built Clang. First, I grabbed the source:
cd tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
... Then, I moved to the just-created source directory, and executed gmake:
cd clang
gmake
My finishing step was to tack the ../llvm/Release/bin and ../llvm/Release/lib paths onto the environment PATH variable.
What follows is a bit of code (from a Four Calorie DNS server project) that I used as bait to test the LLVM Clang compiler.
Rough Drafting Code
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
* main.c
* Copyright (C) Datazygte, Inc - Contrib by Ron Scheckelhoff 2009 <ron@fourcalorieservers.com>
*
* main.cc is free software copyrighted by Datazygte, Inc - Contrib by Ron Scheckelhoff.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name ``Datazygte, Inc - Contrib by Ron Scheckelhoff'' nor the name of any other
* contributor may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* main.c IS PROVIDED BY Datazygte, Inc - Contrib by Ron Scheckelhoff ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Datazygte, Inc - Contrib by Ron Scheckelhoff OR ANY OTHER CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
//
// Specification for labels (Max=7 in DNS spec, but here
// is set to 100 for future expandability)
//
#define EOQ 2
#define MAX_LABEL_LENGTH 128
#define MAX_LABELS 100
#define SUCCESS 0
#define FAILURE 999
#define TIMEOUT 998
#define MAX_CHAR 128
#define MIN_CHAR 28
#define MAX_BUFFER_INPUT_QUERY 2048
#define QUERY_HEADER_OFFSET 12
//
struct STC_QUERY_INPUT_C
{
char bx1_Label_Length;
char bx128_Label[MAX_LABEL_LENGTH];
char bx2_Record_Type[2];
char bx2_Class[2];
};
//
struct STC_QUERY_INPUT_A
{
char bx2_TransactionID[2];
char bx2_Flags[2];
char bx2_Question_Quantity[2];
char bx2_ResRecord_Quantity[2];
char bx2_AuthRecord_Quantity[2];
char bx2_AddRecord_Quantity[2];
};
//
struct STC_QUERY_INPUT_B
{
STC_QUERY_INPUT_A stcQueryHeader;
int intTotalLabelCount;
STC_QUERY_INPUT_C stcLabels[MAX_LABELS];
};
//
// Extract Labels
//
int ExtractLabels(STC_QUERY_INPUT_B* pstcFullQuery,
char cstrBuffer[MAX_BUFFER_INPUT_QUERY], int siz)
{
char* pstrMarker;
STC_QUERY_INPUT_C stcLabel;
STC_QUERY_INPUT_C* pstcLabelForArray;
int intHereBefore = 0;
int intLabelIndex = 1;
int intThisLabelLen = 0;
memset(&stcLabel,0,sizeof(STC_QUERY_INPUT_C));
if (siz < MAX_BUFFER_INPUT_QUERY)
{
for (int i=QUERY_HEADER_OFFSET; i<siz-EOQ; i++)
{
if ((cstrBuffer[i] > MIN_CHAR) && (cstrBuffer[i] < MAX_CHAR))
{
// part of label text - make sure it fits
if ((stcLabel.bx1_Label_Length > 0) &&
(stcLabel.bx1_Label_Length < MAX_LABEL_LENGTH))
{
intThisLabelLen++;
if (intThisLabelLen <= stcLabel.bx1_Label_Length)
{
stcLabel.bx128_Label[intThisLabelLen-1] = cstrBuffer[i];
}
}
}
else
{
// part of label section count
if (intHereBefore != 0)
{
pstcLabelForArray = &pstcFullQuery->stcLabels[intLabelIndex];
memset(pstcLabelForArray, 0, sizeof(STC_QUERY_INPUT_C));
memcpy(pstcLabelForArray->bx128_Label, stcLabel.bx128_Label, MAX_LABEL_LENGTH);
pstcLabelForArray->bx1_Label_Length = stcLabel.bx1_Label_Length;
memset(stcLabel.bx128_Label,0,MAX_LABEL_LENGTH);
intThisLabelLen = 0;
intLabelIndex++;
}
intHereBefore = 1;
stcLabel.bx1_Label_Length = cstrBuffer[i];
// end of all labels
if (cstrBuffer[i] == 0)
{
pstcLabelForArray->bx2_Record_Type[1] = cstrBuffer[i+EOQ];
return intLabelIndex-1;
}
}
}
}
return FAILURE;
}
What Have we Written?
Clang Compiler bits and pieces
Continued post: 04/23/2009
The material on http://llvm.org makes a lot of mention about the compiler not being ready in terms of compiling C++.
Don't let those warnings stand in your way, as I have found that the compiler nicely falls back to g++ to build any
c++ objects in my projects.
The code (shown above) was wrapped up with a few pages more (not shown), and compiled and linked into a program
two or three times faster than it did
with gcc:
clang -o main main.c
To see a full list of the options, type:
clang -help
..... to be continued ...
1Note that this site is not affiliated with or endorsed by http://llvm.org, LLVM, Clang, or UIUC in any way.