]> Zhao Yanbai Git Server - minix.git/commitdiff
LLVM Hello pass: inserts printf statement in main() method.
authorKoustubha Bhat <ksbhat@live.com>
Fri, 6 Jun 2014 14:20:39 +0000 (16:20 +0200)
committerLionel Sambuc <lionel@minix3.org>
Mon, 28 Jul 2014 15:06:04 +0000 (17:06 +0200)
minix/llvm/generate_gold_plugin.sh
minix/llvm/passes/WeakAliasModuleOverride/Makefile
minix/llvm/passes/hello/Makefile [new file with mode: 0644]
minix/llvm/passes/hello/hello.cpp [new file with mode: 0644]
minix/llvm/passes/hello/pass.h [new file with mode: 0644]
minix/llvm/passes/hello/pass_hello.h [new file with mode: 0644]
share/mk/bsd.own.mk

index 9b8f42875a95aa3d3aa6d9454575c64b7ae1d57e..ea88b3cb41c1c3f596fafbc7dfbc082e56125b8a 100755 (executable)
@@ -63,3 +63,5 @@ cp ${OBJ_LLVM}/./Release+Asserts/bin/llvm-* ${CROSS_TOOLS}
 cd ${NETBSDSRCDIR}/minix/llvm/passes/WeakAliasModuleOverride
 make LLVMPREFIX=${OBJ_LLVM}/./Release+Asserts/ install
 
+cd ${NETBSDSRCDIR}/minix/llvm/passes/hello
+make LLVMPREFIX=${OBJ_LLVM}/./Release+Asserts/ install
index 38333d677edfd91729fb196d1bf584d74b9cc772..cb708a802981b9651d5f12f6de98ec3a1855a6e9 100644 (file)
@@ -2,7 +2,7 @@ QUIET=@
 ECHO=echo
 CP=cp
 
-PASSLIBNAME:= weak-alias-module-override
+PASSLIBNAME:= weak-alias-module-override.so
 
 LLVM_VERSION = $($LLVMPREFIX/bin/llvm-config --version | sed "s/[^0-9]//g")
 CFLAGS  += -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -DHAVE_EXCEPTIONS=0
diff --git a/minix/llvm/passes/hello/Makefile b/minix/llvm/passes/hello/Makefile
new file mode 100644 (file)
index 0000000..744dc90
--- /dev/null
@@ -0,0 +1,26 @@
+QUIET=@
+ECHO=echo
+CP=cp
+
+PASSLIBNAME:= hello.so
+
+LLVM_VERSION=$(shell ($(LLVMPREFIX)/bin/llvm-config --version | sed "s/[^0-9]//g"))
+CFLAGS  += -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -DHAVE_EXCEPTIONS=0
+CFLAGS  += $(shell $(LLVMPREFIX)/bin/llvm-config --cxxflags) -g -DLLVM_VERSION=$(LLVM_VERSION)
+LDFLAGS += $(shell $(LLVMPREFIX)/bin/llvm-config --ldflags)
+OBJS= hello.o
+
+$(PASSLIBNAME): $(OBJS)
+       $(QUIET) $(ECHO) "  [LINK] $@"
+       $(QUIET) $(CXX) $(CFLAGS) -shared -o $@ $(CPPS) $(OBJS) $(LDFLAGS) $(LIBS)
+
+%.o: %.cpp $(HEADERS)
+       $(QUIET) $(ECHO)  "  [C++] $<"
+       $(QUIET) $(CXX) $(CFLAGS) -c -o $@ $<
+
+install: $(PASSLIBNAME)
+       $(QUIET) -mkdir -p ../../bin
+       $(QUIET) $(CP)  $(PASSLIBNAME) ../../bin/$(PASSLIBNAME)
+
+clean:
+       -rm -f *.o *.so
diff --git a/minix/llvm/passes/hello/hello.cpp b/minix/llvm/passes/hello/hello.cpp
new file mode 100644 (file)
index 0000000..5d7f9dc
--- /dev/null
@@ -0,0 +1,114 @@
+#include "pass_hello.h"
+#include <stdlib.h>
+
+using namespace llvm;
+
+#define DBG(M) M
+#define helloPassLog(M) DBG(errs() << "HelloPass: " << M << "\n")
+#define MSG   "Hello world!"
+#define ERROR_FAILURE   1
+
+namespace {
+
+  class HelloPass : public ModulePass {
+
+  public:
+    static char ID;
+
+    
+    HelloPass() : ModulePass(ID) { }
+    
+
+    virtual bool runOnModule(Module &M) {
+
+    Function* printfFunction = NULL;
+    Function* mainFunction = NULL;      
+
+    mainFunction = M.getFunction("main");
+    if (NULL == mainFunction)
+    {
+      helloPassLog("Info: main() not found. Skipping instrumentation.");
+      return false;
+    }
+
+    /* Prepare the string arguments for printf */
+    std::string printFuncName = "printf" ;
+    const std::string msg = MSG;
+    const std::string fmt = "%s\n";
+    Constant* strConstMsg = NULL;
+    Constant* strConstFmt = NULL;
+    std::vector<Value*> args(0);
+    Instruction *I = NULL;
+
+    PassUtil::getStringGlobalVariable(M, fmt, ".fmtStr", "", &strConstFmt, false);
+    PassUtil::getStringGlobalVariable(M, msg, ".helloworld", "", &strConstMsg, false);
+
+    if (NULL == strConstFmt || NULL == strConstMsg)
+    {
+         helloPassLog("Error: Prepared string contants point to NULL");
+         exitOnError(ERROR_FAILURE);
+    }
+
+    args.push_back(strConstFmt);
+    args.push_back(strConstMsg);
+    
+    /* Look for printf declaration */
+    std::vector<TYPECONST Type*> functionTyArgs;
+    FunctionType* printfFuncType;
+
+    functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
+    
+    printfFuncType = PassUtil::getFunctionType(IntegerType::get(M.getContext(), 32), functionTyArgs, true);
+    if (NULL == printfFuncType)
+    {
+      helloPassLog("Error: Couldn't make function-type for printf.");
+      exitOnError(ERROR_FAILURE);
+    }
+
+         printfFunction = (Function *) M.getOrInsertFunction(printFuncName, printfFuncType);
+         if (NULL == printfFunction)
+         {
+      helloPassLog("Error: Couldnt find printf function declaration.");
+      exitOnError(ERROR_FAILURE);
+    }
+    
+    /* Insert call instruction in main() to call printf */
+         I = mainFunction->getBasicBlockList().begin()->begin();
+         if (NULL != I)
+         {
+                 if (args.empty())
+                 {
+                         helloPassLog("Warning: args to printf is empty.");
+                 }
+
+                 helloPassLog("Info: Inserting printf call instruction");
+
+                 CallInst* callInst = PassUtil::createCallInstruction(printfFunction, args, "", I);
+
+                 if (NULL == callInst )
+                 {
+                         helloPassLog("Error: callInstr is null.");
+                         exitOnError(ERROR_FAILURE);
+                 }
+
+                 helloPassLog("Info: Inserting call instruction successful.");
+
+                 return true;
+         }
+         
+      return false;
+    }
+
+    private:
+    void exitOnError(int errCode)
+    {
+      helloPassLog("Aborting instrumentation.");
+       exit(errCode);
+    }
+
+  };
+
+}
+
+char HelloPass::ID = 0;
+RegisterPass<HelloPass> HP("hello", "Hello Pass", false, false);
diff --git a/minix/llvm/passes/hello/pass.h b/minix/llvm/passes/hello/pass.h
new file mode 100644 (file)
index 0000000..59e5429
--- /dev/null
@@ -0,0 +1,35 @@
+
+#ifndef _PASS_H
+#define _PASS_H
+
+#import <set>
+#import <map>
+
+#include <llvm/Pass.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Analysis/AliasAnalysis.h>
+
+#include <llvm/Support/Debug.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+#include <llvm/ADT/Statistic.h>
+
+#include <llvm/Support/Regex.h>
+#include <llvm/Assembly/Writer.h>
+#include <llvm/Support/CallSite.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Analysis/LoopInfo.h>
+
+#include <llvm/Support/InstIterator.h>
+#include <llvm/Transforms/Utils/Local.h>
+
+#include <llvm/Transforms/Scalar.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <common/pass_common.h>
+
+#endif /* _PASS_H */
diff --git a/minix/llvm/passes/hello/pass_hello.h b/minix/llvm/passes/hello/pass_hello.h
new file mode 100644 (file)
index 0000000..9d1f15e
--- /dev/null
@@ -0,0 +1,224 @@
+#ifndef _PASS_HELLO_H
+#define _PASS_HELLO_H
+
+#if LLVM_VERSION >= 33
+#define ATTRIBUTE_SET_TY              AttributeSet
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/Intrinsics.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/IntrinsicInst.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/Support/raw_ostream.h>
+#else /* LLVM_VERSION < 33 */
+#define ATTRIBUTE_SET_TY              AttrListPtr
+#include <llvm/Function.h>
+#include <llvm/Module.h>
+#include <llvm/Instructions.h>
+#include <llvm/Type.h>
+#include <llvm/Constants.h>
+#include <llvm/Intrinsics.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/IntrinsicInst.h>
+#endif /* LLVM_VERSION >= 33 */
+
+#if LLVM_VERSION >= 32
+#define DATA_LAYOUT_TY                       DataLayout
+#define ATTRIBUTE_SET_RET_IDX         ATTRIBUTE_SET_TY::ReturnIndex
+#define ATTRIBUTE_SET_FN_IDX          ATTRIBUTE_SET_TY::FunctionIndex
+#include <llvm/DebugInfo.h>
+#if LLVM_VERSION == 32
+#include <llvm/DataLayout.h>
+#include <llvm/IRBuilder.h>
+#endif
+#else /* LLVM_VERSION < 32 */
+#define DATA_LAYOUT_TY                       TargetData
+#define ATTRIBUTE_SET_RET_IDX         0
+#define ATTRIBUTE_SET_FN_IDX          (~0U)
+#include <llvm/Target/TargetData.h>
+#include <llvm/Analysis/DebugInfo.h>
+#include <llvm/Support/IRBuilder.h>
+#endif /* LLVM_VERSION >= 32 */
+
+#if LLVM_VERSION >= 31
+/* XXX Check. */
+#define CONSTANT_ARRAY_INITIALIZER_TY ConstantDataArray
+
+#else /* LLVM_VERSION < 31 */
+#define CONSTANT_ARRAY_INITIALIZER_TY ConstantArray
+#endif /* LLVM_VERSION >= 31 */
+
+#if LLVM_VERSION >= 30
+#define BASE_PARSER                   parser
+
+#define TYPECONST
+#else /* LLVM_VERSION < 30 */
+#define BASE_PARSER                   basic_parser
+
+#define TYPECONST const
+#endif /* LLVM_VERSION >= 30 */
+
+#if LLVM_VERSION >= 29
+#define VALUE_TO_VALUE_MAP_TY ValueToValueMapTy
+#else  /* LLVM_VERSION < 29 */
+#define VALUE_TO_VALUE_MAP_TY ValueMap<const Value*, Value*>
+#endif /* LLVM_VERSION >= 29 */
+
+#define ZERO_CONSTANT_INT(M) ConstantInt::get((M).getContext(), APInt(32, 0, 10))
+#define VOID_PTR_TY(M)       PointerType::get(IntegerType::get((M).getContext(), 8), 0)
+#define VOID_PTR_PTR_TY(M)   PointerType::get(PointerType::get(IntegerType::get((M).getContext(), 8), 0), 0)
+
+#define DEBUG_LLVM_DEBUG_API 0
+
+typedef enum PassUtilLinkageTypeE {
+    PASS_UTIL_LINKAGE_NONE = 0,
+    PASS_UTIL_LINKAGE_WEAK,
+    PASS_UTIL_LINKAGE_COMMON,
+    PASS_UTIL_LINKAGE_EXTERNAL,
+    PASS_UTIL_LINKAGE_EXTERNAL_WEAK,
+    PASS_UTIL_LINKAGE_WEAK_POINTER,
+    PASS_UTIL_LINKAGE_PRIVATE,
+    __NUM_PASS_UTIL_LINKAGE_TYPES
+    /* Values here should only be appended at the end, external components (e.g., scripts) may be relying on them.*/
+} PassUtilLinkageType;
+
+#define PASS_UTIL_LINKAGE_TYPE_STRINGS \
+    "NONE", \
+    "WEAK", \
+    "COMMON", \
+    "EXTERNAL", \
+    "EXTERNAL_WEAK", \
+    "WEAK_POINTER", \
+    "PRIVATE"
+
+typedef enum PassUtilPropE {
+    PASS_UTIL_PROP_NONE,
+    PASS_UTIL_PROP_NOINLINE,
+    PASS_UTIL_PROP_USED,
+    PASS_UTIL_PROP_PRESERVE,
+    __NUM_PASS_UTIL_PROPS
+} PassUtilProp;
+
+#define PASS_UTIL_FLAG(F) (1 << F)
+
+#define PASS_COMMON_INIT_ONCE() \
+    Module *PassUtil::M = NULL; \
+
+using namespace llvm;
+
+namespace llvm {
+
+class PassUtil {
+  public:
+      static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
+      static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
+      static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
+      static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg=false);
+      static Constant* getStringConstantArray(Module &M, const std::string &string);
+      static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false);
+  private:
+      static Module *M;
+};
+
+inline Constant* PassUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
+#if LLVM_VERSION >= 30
+    ArrayRef<Value*> ref(indexes);
+    return ConstantExpr::getGetElementPtr(constant, ref);
+#else
+    return ConstantExpr::getGetElementPtr(constant, &indexes[0], indexes.size());
+#endif
+}
+
+inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
+#if LLVM_VERSION >= 30
+    ArrayRef<Value*> ref(args);
+    return CallInst::Create(F, ref, NameStr, InsertBefore);
+#else
+    return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertBefore);
+#endif
+}
+
+inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+#if LLVM_VERSION >= 30
+    ArrayRef<Value*> ref(args);
+    return CallInst::Create(F, ref, NameStr, InsertAtEnd);
+#else
+    return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertAtEnd);
+#endif
+}
+
+inline FunctionType* PassUtil::getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg)
+{
+#if LLVM_VERSION >= 30
+    ArrayRef<TYPECONST Type*> ref(argsTy);
+    return FunctionType::get(Result, ref, isVarArg);
+#else
+    return FunctionType::get(Result, argsTy, isVarArg);
+#endif
+}
+
+
+inline Constant* PassUtil::getStringConstantArray(Module &M, const std::string &string)
+{
+  std::vector<Constant*> elements;
+  elements.reserve(string.size() + 1);
+  for (unsigned i = 0; i < string.size(); ++i)
+    elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), string[i]));
+
+  // Add a null terminator to the string...
+  elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0));
+
+  ArrayType *ATy = ArrayType::get(Type::getInt8Ty(M.getContext()), elements.size());
+  return ConstantArray::get(ATy, elements);
+}
+
+inline GlobalVariable* PassUtil::getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection, Constant **getElementPtrExpr, bool cacheable)
+{
+    static std::map<std::string, GlobalVariable*> stringCache;
+    std::map<std::string, GlobalVariable*>::iterator stringCacheIt;
+    std::string stringCacheKey;
+    GlobalVariable *strGV = NULL;
+
+    if (cacheable) {
+       stringCacheKey = string + "~!~!" + varName + "~!~!" + varSection;
+        stringCacheIt = stringCache.find(stringCacheKey);
+        if (stringCacheIt != stringCache.end()) {
+            strGV = stringCacheIt->second;
+            cacheable = false;
+        }
+    }
+
+    if (!strGV) {
+        //create a constant internal string reference
+        Constant *stringValue = PassUtil::getStringConstantArray(M, string);
+
+        //create the global variable, cache it, and record it in the module
+        strGV = new GlobalVariable(M, stringValue->getType(), true,
+            GlobalValue::InternalLinkage, stringValue, varName);
+        if (varSection.compare("")) {
+            strGV->setSection(varSection);
+        }
+    }
+    if (getElementPtrExpr) {
+           std::vector<Value*> strConstantIndices;
+           strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
+           strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
+           *getElementPtrExpr = PassUtil::getGetElementPtrConstant(strGV, strConstantIndices);
+    }
+
+    if (cacheable) {
+        stringCache.insert(std::pair<std::string, GlobalVariable*>(stringCacheKey, strGV));
+    }
+
+    return strGV;
+}
+
+}
+
+#endif /* _PASS_HELLO_H */
index 208e74867a8aafbf89ae739878900cff5c460041..4de947a63625c8bb70dc088c88c6c2dd3c1201eb 100644 (file)
@@ -61,7 +61,7 @@ MKRUMP:=      no
 MKSKEY:=       no
 MKYP:=         no
 
-WEAKALIASOVERRIDEPASS?=${NETBSDSRCDIR}/minix/llvm/bin/weak-alias-module-override
+WEAKALIASOVERRIDEPASS?=${NETBSDSRCDIR}/minix/llvm/bin/weak-alias-module-override.so
 GOLD_PLUGIN?=${NETBSDSRCDIR}/minix/llvm/bin/LLVMgold.so
 
 # By default when running LLVM passes:
@@ -69,6 +69,7 @@ GOLD_PLUGIN?=${NETBSDSRCDIR}/minix/llvm/bin/LLVMgold.so
 #  -  run the passe which allows assembly weak symbols to be
 #     overriden by bitcode functions
 OPTFLAGS?=     -disable-opt \
+               -disable-internalize -disable-inlining \
                -load ${WEAKALIASOVERRIDEPASS} -weak-alias-module-override
 
 # Whitout -Wl,--no-ctors-in-init-array, golds moves the constructors out of